// validat5.cpp - originally written and placed in the public domain by Wei Dai
//                CryptoPP::Test namespace added by JW in February 2017.
//                Source files split in July 2018 to expedite compiles.

#include "pch.h"

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1

#include "cryptlib.h"
#include "cpu.h"
#include "validate.h"

#include "aes.h"
#include "crc.h"
#include "adler32.h"

#include "md2.h"
#include "md4.h"
#include "md5.h"

#include "sha.h"
#include "sha3.h"
#include "shake.h"
#include "keccak.h"
#include "tiger.h"
#include "blake2.h"
#include "ripemd.h"
#include "siphash.h"
#include "poly1305.h"
#include "whrlpool.h"
#include "lsh.h"

#include "pssr.h"
#include "hkdf.h"
#include "scrypt.h"
#include "pwdbased.h"

#include "cmac.h"
#include "dmac.h"
#include "hmac.h"
#include "ttmac.h"

#include <iostream>
#include <iomanip>
#include <sstream>

// Aggressive stack checking with VS2005 SP1 and above.
#if (_MSC_FULL_VER >= 140050727)
# pragma strict_gs_check (on)
#endif

#if CRYPTOPP_MSC_VERSION
# pragma warning(disable: 4505 4355)
#endif

NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test)

struct HashTestTuple
{
	HashTestTuple(const char *input, const char *output, unsigned int repeatTimes=1)
		: input((byte *)input), output((byte *)output), inputLen(strlen(input)), repeatTimes(repeatTimes) {}

	HashTestTuple(const char *input, unsigned int inputLen, const char *output, unsigned int repeatTimes)
		: input((byte *)input), output((byte *)output), inputLen(inputLen), repeatTimes(repeatTimes) {}

	const byte *input, *output;
	size_t inputLen, repeatTimes;
};

bool HashModuleTest(HashTransformation &md, const HashTestTuple *testSet, size_t testSetSize)
{
	bool pass=true, fail;
	std::ostringstream oss;

	SecByteBlock digest(md.DigestSize());
	for (size_t i=0; i<testSetSize; i++)
	{
		size_t j;

		for (j=0; j<testSet[i].repeatTimes; j++)
			md.Update(testSet[i].input, testSet[i].inputLen);
		md.Final(digest);
		fail = std::memcmp(digest, testSet[i].output, md.DigestSize()) != 0;
		pass = pass && !fail;

		oss << (fail ? "FAILED   " : "passed   ");
		for (j=0; j<md.DigestSize(); j++)
			oss << std::setw(2) << std::setfill('0') << std::hex << (int)digest[j];
		oss << "   \"" << (char *)testSet[i].input << '\"';
		if (testSet[i].repeatTimes != 1)
			oss << " repeated " << std::dec << testSet[i].repeatTimes << " times";
		oss  << std::endl;
	}

	std::cout << oss.str();
	return pass;
}

bool ValidateCRC32()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x00\x00\x00\x00"),
		HashTestTuple("a", "\x43\xbe\xb7\xe8"),
		HashTestTuple("abc", "\xc2\x41\x24\x35"),
		HashTestTuple("message digest", "\x7f\x9d\x15\x20"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xbd\x50\x27\x4c"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xd2\xe6\xc2\x1f"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x72\x4a\xa9\x7c"),
		HashTestTuple("123456789", "\x26\x39\xf4\xcb")
	};

	CRC32 crc;

	std::cout << "\nCRC-32 validation suite running...\n\n";
	return HashModuleTest(crc, testSet, COUNTOF(testSet));
}

bool ValidateCRC32C()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x00\x00\x00\x00"),
		HashTestTuple("a", "\x30\x43\xd0\xc1"),
		HashTestTuple("abc", "\xb7\x3f\x4b\x36"),
		HashTestTuple("message digest", "\xd0\x79\xbd\x02"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x25\xef\xe6\x9e"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x7d\xd5\x45\xa2"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x81\x67\x7a\x47"),
		HashTestTuple("123456789", "\x83\x92\x06\xe3")
	};

	CRC32C crc;

	std::cout << "\nCRC-32C validation suite running...\n\n";
	return HashModuleTest(crc, testSet, COUNTOF(testSet));
}

bool ValidateAdler32()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x00\x00\x00\x01"),
		HashTestTuple("a", "\x00\x62\x00\x62"),
		HashTestTuple("abc", "\x02\x4d\x01\x27"),
		HashTestTuple("message digest", "\x29\x75\x05\x86"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x90\x86\x0b\x20"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x8a\xdb\x15\x0c"),
		HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x15\xd8\x70\xf9", 15625)
	};

	Adler32 md;

	std::cout << "\nAdler-32 validation suite running...\n\n";
	return HashModuleTest(md, testSet, COUNTOF(testSet));
}

bool ValidateMD2()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73"),
		HashTestTuple("a", "\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0\xb5\xd1"),
		HashTestTuple("abc", "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde\xd6\xbb"),
		HashTestTuple("message digest", "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xda\x33\xde\xf2\xa4\x2d\xf1\x39\x75\x35\x28\x46\xc3\x03\x38\xcd"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8")
	};

	Weak::MD2 md2;

	std::cout << "\nMD2 validation suite running...\n\n";
	return HashModuleTest(md2, testSet, COUNTOF(testSet));
}

bool ValidateMD4()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0"),
		HashTestTuple("a", "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24"),
		HashTestTuple("abc", "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d"),
		HashTestTuple("message digest", "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d\xa9"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05\x36")
	};

	Weak::MD4 md4;

	std::cout << "\nMD4 validation suite running...\n\n";
	return HashModuleTest(md4, testSet, COUNTOF(testSet));
}

bool ValidateMD5()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e"),
		HashTestTuple("a", "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61"),
		HashTestTuple("abc", "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72"),
		HashTestTuple("message digest", "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a")
	};

	Weak::MD5 md5;

	std::cout << "\nMD5 validation suite running...\n\n";
	return HashModuleTest(md5, testSet, COUNTOF(testSet));
}

bool ValidateSHA()
{
	std::cout << "\nSHA validation suite running...\n";
	return RunTestDataFile("TestVectors/sha.txt");
}

bool ValidateSHA2()
{
	std::cout << "\nSHA-2 validation suite running...\n";
	return RunTestDataFile("TestVectors/sha2.txt");
}

bool ValidateKeccak()
{
	std::cout << "\nKeccak validation suite running...\n";
	return RunTestDataFile("TestVectors/keccak.txt");
}

bool ValidateSHA3()
{
	std::cout << "\nSHA-3 validation suite running...\n";
	return RunTestDataFile("TestVectors/sha3.txt");
}

bool ValidateSHAKE()
{
	std::cout << "\nSHAKE validation suite running...\n";
	return RunTestDataFile("TestVectors/shake.txt");
}

// We needed to hand craft the SHAKE tests because SHAKE128 and SHAKE256
// use digestSize 'd' as an input parameter for the hash. When 'd > r',
// where 'r' is rate and acts like a blockSize, then TruncatedFinal acts
// like a traditional KDF and applies KeccakF1600 core function multiple
// times on state to create the stream. Regarding the NIST test vectors,
// the SHAKE128 KATs do not engage 'd > r'. However, the SHAKE256 KATs
// do engage it.
bool ValidateSHAKE_XOF()
{
	std::cout << "\nSHAKE XOF validation suite running...\n";
	bool pass = true, fail;

	////// NIST test vectors SHAKE128VariableOut.rsp //////

	// SHAKE128, COUNT = 0 (first test)
	{
		std::string m, msg = "84e950051876050dc851fbd99e6247b8";
		std::string o, out = "8599bd89f63a848c49ca593ec37a12c6";
		std::string r;

		StringSource(msg, true, new HexDecoder(new StringSink(m)));
		StringSource(out, true, new HexDecoder(new StringSink(o)));
		r.resize(o.size());

		SHAKE128 hash((unsigned int)o.size());
		hash.Update(ConstBytePtr(m), BytePtrSize(m));
		hash.TruncatedFinal(BytePtr(r), BytePtrSize(r));

		fail = r != o;
		pass = pass & !fail;

		if (fail)
			std::cout << "FAILED   " << "SHAKE128 test COUNT=0" << std::endl;

		pass = pass && !fail;
	}

	// SHAKE128, COUNT = 1125 (last test)
	{
		std::string m, msg = "0a13ad2c7a239b4ba73ea6592ae84ea9";
		std::string o, out = "5feaf99c15f48851943ff9baa6e5055d 8377f0dd347aa4dbece51ad3a6d9ce0c"
		                     "01aee9fe2260b80a4673a909b532adcd d1e421c32d6460535b5fe392a58d2634"
		                     "979a5a104d6c470aa3306c400b061db9 1c463b2848297bca2bc26d1864ba49d7"
		                     "ff949ebca50fbf79a5e63716dc82b600 bd52ca7437ed774d169f6bf02e464879"
		                     "56fba2230f34cd2a0485484d";
		std::string r;

		StringSource(msg, true, new HexDecoder(new StringSink(m)));
		StringSource(out, true, new HexDecoder(new StringSink(o)));
		r.resize(o.size());

		SHAKE128 hash((unsigned int)o.size());
		hash.Update(ConstBytePtr(m), BytePtrSize(m));
		hash.TruncatedFinal(BytePtr(r), BytePtrSize(r));

		fail = r != o;
		pass = pass & !fail;

		if (fail)
			std::cout << "FAILED   " << "SHAKE128 test COUNT=1125" << std::endl;

		pass = pass && !fail;
	}

	////// NIST test vectors SHAKE256VariableOut.rsp //////

	// SHAKE256, COUNT = 0 (first test)
	{
		std::string m, msg = "c61a9188812ae73994bc0d6d4021e31b f124dc72669749111232da7ac29e61c4";
		std::string o, out = "23ce";
		std::string r;

		StringSource(msg, true, new HexDecoder(new StringSink(m)));
		StringSource(out, true, new HexDecoder(new StringSink(o)));
		r.resize(o.size());

		SHAKE256 hash((unsigned int)o.size());
		hash.Update(ConstBytePtr(m), BytePtrSize(m));
		hash.TruncatedFinal(BytePtr(r), BytePtrSize(r));

		fail = r != o;
		pass = pass & !fail;

		if (fail)
			std::cout << "FAILED   " << "SHAKE256 test COUNT=0" << std::endl;

		pass = pass && !fail;
	}

	// SHAKE256, COUNT = 1245 (last test)
	{
		std::string m, msg = "8d8001e2c096f1b88e7c9224a086efd4 797fbf74a8033a2d422a2b6b8f6747e4";
		std::string o, out = "2e975f6a8a14f0704d51b13667d8195c 219f71e6345696c49fa4b9d08e9225d3"
		                     "d39393425152c97e71dd24601c11abcf a0f12f53c680bd3ae757b8134a9c10d4"
		                     "29615869217fdd5885c4db174985703a 6d6de94a667eac3023443a8337ae1bc6"
		                     "01b76d7d38ec3c34463105f0d3949d78 e562a039e4469548b609395de5a4fd43"
		                     "c46ca9fd6ee29ada5efc07d84d553249 450dab4a49c483ded250c9338f85cd93"
		                     "7ae66bb436f3b4026e859fda1ca57143 2f3bfc09e7c03ca4d183b741111ca048"
		                     "3d0edabc03feb23b17ee48e844ba2408 d9dcfd0139d2e8c7310125aee801c61a"
		                     "b7900d1efc47c078281766f361c5e611 1346235e1dc38325666c";
		std::string r;

		StringSource(msg, true, new HexDecoder(new StringSink(m)));
		StringSource(out, true, new HexDecoder(new StringSink(o)));
		r.resize(o.size());

		SHAKE256 hash((unsigned int)o.size());
		hash.Update(ConstBytePtr(m), BytePtrSize(m));
		hash.TruncatedFinal(BytePtr(r), BytePtrSize(r));

		fail = r != o;
		pass = pass & !fail;

		if (fail)
			std::cout << "FAILED   " << "SHAKE256 test COUNT=0" << std::endl;

		pass = pass && !fail;
	}

	std::cout << (!pass ? "FAILED   " : "passed   ") << "SHAKE XOF message digests" << std::endl;

	return pass;
}

bool ValidateTiger()
{
	std::cout << "\nTiger validation suite running...\n\n";

	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\x32\x93\xac\x63\x0c\x13\xf0\x24\x5f\x92\xbb\xb1\x76\x6e\x16\x16\x7a\x4e\x58\x49\x2d\xde\x73\xf3"),
		HashTestTuple("a", "\x77\xBE\xFB\xEF\x2E\x7E\xF8\xAB\x2E\xC8\xF9\x3B\xF5\x87\xA7\xFC\x61\x3E\x24\x7F\x5F\x24\x78\x09"),
		HashTestTuple("abc", "\x2a\xab\x14\x84\xe8\xc1\x58\xf2\xbf\xb8\xc5\xff\x41\xb5\x7a\x52\x51\x29\x13\x1c\x95\x7b\x5f\x93"),
		HashTestTuple("Tiger", "\xdd\x00\x23\x07\x99\xf5\x00\x9f\xec\x6d\xeb\xc8\x38\xbb\x6a\x27\xdf\x2b\x9d\x6f\x11\x0c\x79\x37"),
		HashTestTuple("message digest", "\xD9\x81\xF8\xCB\x78\x20\x1A\x95\x0D\xCF\x30\x48\x75\x1E\x44\x1C\x51\x7F\xCA\x1A\xA5\x5A\x29\xF6"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x8d\xce\xa6\x80\xa1\x75\x83\xee\x50\x2b\xa3\x8a\x3c\x36\x86\x51\x89\x0f\xfb\xcc\xdc\x49\xa8\xcc"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", "\xf7\x1c\x85\x83\x90\x2a\xfb\x87\x9e\xdf\xe6\x10\xf8\x2c\x0d\x47\x86\xa3\xa5\x34\x50\x44\x86\xb5"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", "\x48\xce\xeb\x63\x08\xb8\x7d\x46\xe9\x5d\x65\x61\x12\xcd\xf1\x8d\x97\x91\x5f\x97\x65\x65\x89\x57"),
		HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", "\x8a\x86\x68\x29\x04\x0a\x41\x0c\x72\x9a\xd2\x3f\x5a\xda\x71\x16\x03\xb3\xcd\xd3\x57\xe4\xc1\x5e"),
		HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.", "\xce\x55\xa6\xaf\xd5\x91\xf5\xeb\xac\x54\x7f\xf8\x4f\x89\x22\x7f\x93\x31\xda\xb0\xb6\x11\xc8\x89"),
		HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.", "\x63\x1a\xbd\xd1\x03\xeb\x9a\x3d\x24\x5b\x6d\xfd\x4d\x77\xb2\x57\xfc\x74\x39\x50\x1d\x15\x68\xdd"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", "\xc5\x40\x34\xe5\xb4\x3e\xb8\x00\x58\x48\xa7\xe0\xae\x6a\xac\x76\xe4\xff\x59\x0a\xe7\x15\xfd\x25")
	};

	Tiger tiger;

	return HashModuleTest(tiger, testSet, COUNTOF(testSet));
}

bool ValidateRIPEMD()
{
	const HashTestTuple testSet128[] =
	{
		HashTestTuple("", "\xcd\xf2\x62\x13\xa1\x50\xdc\x3e\xcb\x61\x0f\x18\xf6\xb3\x8b\x46"),
		HashTestTuple("a", "\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7\xcf\xc7\x85\xe7\x2f\x57\x8d\x33"),
		HashTestTuple("abc", "\xc1\x4a\x12\x19\x9c\x66\xe4\xba\x84\x63\x6b\x0f\x69\x14\x4c\x77"),
		HashTestTuple("message digest", "\x9e\x32\x7b\x3d\x6e\x52\x30\x62\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5\x10\x71\x49\x22\xb3\x71\x83\x4e"),
		HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d\xdc\x22\xe8\x8b\x49\x13\x3a\x06"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xd1\xe9\x59\xeb\x17\x9c\x91\x1f\xae\xa4\x62\x4c\x60\xc5\xc7\x02"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x3f\x45\xef\x19\x47\x32\xc2\xdb\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3"),
		HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x4a\x7f\x57\x23\xf9\x54\xeb\xa1\x21\x6c\x9d\x8f\x63\x20\x43\x1f", 15625)
	};

	const HashTestTuple testSet160[] =
	{
		HashTestTuple("", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31"),
		HashTestTuple("a", "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe"),
		HashTestTuple("abc", "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc"),
		HashTestTuple("message digest", "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc"),
		HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab\x82\xbf\x63\x32\x6b\xfb"),
		HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83\x25\xdc\x15\x28", 15625)
	};

	const HashTestTuple testSet256[] =
	{
		HashTestTuple("", "\x02\xba\x4c\x4e\x5f\x8e\xcd\x18\x77\xfc\x52\xd6\x4d\x30\xe3\x7a\x2d\x97\x74\xfb\x1e\x5d\x02\x63\x80\xae\x01\x68\xe3\xc5\x52\x2d"),
		HashTestTuple("a", "\xf9\x33\x3e\x45\xd8\x57\xf5\xd9\x0a\x91\xba\xb7\x0a\x1e\xba\x0c\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf\xcd\x88\x3a\x91\x34\x69\x29\x25"),
		HashTestTuple("abc", "\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb\xce\xf5\xca\x2d\x03\xe6\xdb\xa1\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e\x1e\x42\xd2\xe9\x75\x45\x9b\x65"),
		HashTestTuple("message digest", "\x87\xe9\x71\x75\x9a\x1c\xe4\x7a\x51\x4d\x5c\x91\x4c\x39\x2c\x90\x18\xc7\xc4\x6b\xc1\x44\x65\x55\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x64\x9d\x30\x34\x75\x1e\xa2\x16\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc\x78\x96\x11\x8a\x51\x97\x96\x87\x82\xdd\x1f\xd9\x7d\x8d\x51\x33"),
		HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x38\x43\x04\x55\x83\xaa\xc6\xc8\xc8\xd9\x12\x85\x73\xe7\xa9\x80\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x57\x40\xa4\x08\xac\x16\xb7\x20\xb8\x44\x24\xae\x93\x1c\xbb\x1f\xe3\x63\xd1\xd0\xbf\x40\x17\xf1\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x06\xfd\xcc\x7a\x40\x95\x48\xaa\xf9\x13\x68\xc0\x6a\x62\x75\xb5\x53\xe3\xf0\x99\xbf\x0e\xa4\xed\xfd\x67\x78\xdf\x89\xa8\x90\xdd"),
		HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xac\x95\x37\x44\xe1\x0e\x31\x51\x4c\x15\x0d\x4d\x8d\x7b\x67\x73\x42\xe3\x33\x99\x78\x82\x96\xe4\x3a\xe4\x85\x0c\xe4\xf9\x79\x78", 15625)
	};

	const HashTestTuple testSet320[] =
	{
		HashTestTuple("", "\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8"),
		HashTestTuple("a", "\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d"),
		HashTestTuple("abc", "\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d"),
		HashTestTuple("message digest", "\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09"),
		HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4"),
		HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42"),
		HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xbd\xee\x37\xf4\x37\x1e\x20\x64\x6b\x8b\x0d\x86\x2d\xda\x16\x29\x2a\xe3\x6f\x40\x96\x5e\x8c\x85\x09\xe6\x3d\x1d\xbd\xde\xcc\x50\x3e\x2b\x63\xeb\x92\x45\xbb\x66", 15625)
	};

	bool pass = true;

	std::cout << "\nRIPEMD-128 validation suite running...\n\n";
	RIPEMD128 md128;
	pass = HashModuleTest(md128, testSet128, COUNTOF(testSet128)) && pass;

	std::cout << "\nRIPEMD-160 validation suite running...\n\n";
	RIPEMD160 md160;
	pass = HashModuleTest(md160, testSet160, COUNTOF(testSet160)) && pass;

	std::cout << "\nRIPEMD-256 validation suite running...\n\n";
	RIPEMD256 md256;
	pass = HashModuleTest(md256, testSet256, COUNTOF(testSet256)) && pass;

	std::cout << "\nRIPEMD-320 validation suite running...\n\n";
	RIPEMD320 md320;
	pass = HashModuleTest(md320, testSet320, COUNTOF(testSet320)) && pass;

	return pass;
}

#ifdef CRYPTOPP_REMOVED
bool ValidateHAVAL()
{
	const HashTestTuple testSet[] =
	{
		HashTestTuple("", "\xC6\x8F\x39\x91\x3F\x90\x1F\x3D\xDF\x44\xC7\x07\x35\x7A\x7D\x70"),
		HashTestTuple("a", "\x4D\xA0\x8F\x51\x4A\x72\x75\xDB\xC4\xCE\xCE\x4A\x34\x73\x85\x98\x39\x83\xA8\x30"),
		HashTestTuple("HAVAL", "\x0C\x13\x96\xD7\x77\x26\x89\xC4\x67\x73\xF3\xDA\xAC\xA4\xEF\xA9\x82\xAD\xBF\xB2\xF1\x46\x7E\xEA"),
		HashTestTuple("0123456789", "\xBE\xBD\x78\x16\xF0\x9B\xAE\xEC\xF8\x90\x3B\x1B\x9B\xC6\x72\xD9\xFA\x42\x8E\x46\x2B\xA6\x99\xF8\x14\x84\x15\x29"),
		HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xC9\xC7\xD8\xAF\xA1\x59\xFD\x9E\x96\x5C\xB8\x3F\xF5\xEE\x6F\x58\xAE\xDA\x35\x2C\x0E\xFF\x00\x55\x48\x15\x3A\x61\x55\x1C\x38\xEE"),
		HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xB4\x5C\xB6\xE6\x2F\x2B\x13\x20\xE4\xF8\xF1\xB0\xB2\x73\xD4\x5A\xDD\x47\xC3\x21\xFD\x23\x99\x9D\xCF\x40\x3A\xC3\x76\x36\xD9\x63")
	};

	bool pass=true;

	std::cout << "\nHAVAL validation suite running...\n\n";
	{
		HAVAL3 md(16);
		pass = HashModuleTest(md, testSet+0, 1) && pass;
	}
	{
		HAVAL3 md(20);
		pass = HashModuleTest(md, testSet+1, 1) && pass;
	}
	{
		HAVAL4 md(24);
		pass = HashModuleTest(md, testSet+2, 1) && pass;
	}
	{
		HAVAL4 md(28);
		pass = HashModuleTest(md, testSet+3, 1) && pass;
	}
	{
		HAVAL5 md(32);
		pass = HashModuleTest(md, testSet+4, 1) && pass;
	}
	{
		HAVAL5 md(32);
		pass = HashModuleTest(md, testSet+5, 1) && pass;
	}

	return pass;
}
#endif

bool ValidatePanama()
{
	std::cout << "\nPanama validation suite running...\n";
	return RunTestDataFile("TestVectors/panama.txt");
}

bool ValidateWhirlpool()
{
	std::cout << "\nWhirlpool validation suite running...\n";
	return RunTestDataFile("TestVectors/whrlpool.txt");
}

bool ValidateLSH()
{
	std::cout << "\nLSH validation suite running...\n";
	return RunTestDataFile("TestVectors/lsh.txt");
}

#ifdef CRYPTOPP_REMOVED
bool ValidateMD5MAC()
{
	const byte keys[2][MD5MAC::KEYLENGTH]={
		{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff},
		{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}};

	const char *TestVals[7]={
		"",
		"a",
		"abc",
		"message digest",
		"abcdefghijklmnopqrstuvwxyz",
		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
		"12345678901234567890123456789012345678901234567890123456789012345678901234567890"};

	const byte output[2][7][MD5MAC::DIGESTSIZE]={
		{{0x1f,0x1e,0xf2,0x37,0x5c,0xc0,0xe0,0x84,0x4f,0x98,0xe7,0xe8,0x11,0xa3,0x4d,0xa8},
		{0x7a,0x76,0xee,0x64,0xca,0x71,0xef,0x23,0x7e,0x26,0x29,0xed,0x94,0x52,0x73,0x65},
		{0xe8,0x01,0x3c,0x11,0xf7,0x20,0x9d,0x13,0x28,0xc0,0xca,0xa0,0x4f,0xd0,0x12,0xa6},
		{0xc8,0x95,0x53,0x4f,0x22,0xa1,0x74,0xbc,0x3e,0x6a,0x25,0xa2,0xb2,0xef,0xd6,0x30},
		{0x91,0x72,0x86,0x7e,0xb6,0x00,0x17,0x88,0x4c,0x6f,0xa8,0xcc,0x88,0xeb,0xe7,0xc9},
		{0x3b,0xd0,0xe1,0x1d,0x5e,0x09,0x4c,0xb7,0x1e,0x35,0x44,0xac,0xa9,0xb8,0xbf,0xa2},
		{0x93,0x37,0x16,0x64,0x44,0xcc,0x95,0x35,0xb7,0xd5,0xb8,0x0f,0x91,0xe5,0x29,0xcb}},
		{{0x2f,0x6e,0x73,0x13,0xbf,0xbb,0xbf,0xcc,0x3a,0x2d,0xde,0x26,0x8b,0x59,0xcc,0x4d},
		{0x69,0xf6,0xca,0xff,0x40,0x25,0x36,0xd1,0x7a,0xe1,0x38,0x03,0x2c,0x0c,0x5f,0xfd},
		{0x56,0xd3,0x2b,0x6c,0x34,0x76,0x65,0xd9,0x74,0xd6,0xf7,0x5c,0x3f,0xc6,0xf0,0x40},
		{0xb8,0x02,0xb2,0x15,0x4e,0x59,0x8b,0x6f,0x87,0x60,0x56,0xc7,0x85,0x46,0x2c,0x0b},
		{0x5a,0xde,0xf4,0xbf,0xf8,0x04,0xbe,0x08,0x58,0x7e,0x94,0x41,0xcf,0x6d,0xbd,0x57},
		{0x18,0xe3,0x49,0xa5,0x24,0x44,0xb3,0x0e,0x5e,0xba,0x5a,0xdd,0xdc,0xd9,0xf1,0x8d},
		{0xf2,0xb9,0x06,0xa5,0xb8,0x4b,0x9b,0x4b,0xbe,0x95,0xed,0x32,0x56,0x4e,0xe7,0xeb}}};

	byte digest[MD5MAC::DIGESTSIZE];
	bool pass=true, fail;
	std::ostringstream oss;

	oss << "\nMD5MAC validation suite running...\n";

	for (int k=0; k<2; k++)
	{
		MD5MAC mac(keys[k]);
		oss << "\nKEY: ";
		for (int j=0;j<MD5MAC::KEYLENGTH;j++)
			oss << std::setw(2) << std::setfill('0') << std::hex << (int)keys[k][j];
		oss << std::endl << std::endl;
		for (int i=0;i<7;i++)
		{
			mac.Update((byte *)TestVals[i], strlen(TestVals[i]));
			mac.Final(digest);
			fail = std::memcmp(digest, output[k][i], MD5MAC::DIGESTSIZE) != 0
				 || !mac.VerifyDigest(output[k][i], (byte *)TestVals[i], strlen(TestVals[i]));
			pass = pass && !fail;
			oss << (fail ? "FAILED   " : "passed   ");
			for (int j=0;j<MD5MAC::DIGESTSIZE;j++)
				oss << std::setw(2) << std::setfill('0') << std::hex << (int)digest[j];
			oss << "   \"" << TestVals[i] << '\"' << std::endl;
		}
	}

	std::cout << oss.str();
	return pass;
}
#endif

bool ValidateHMAC()
{
	return RunTestDataFile("TestVectors/hmac.txt");
}

#ifdef CRYPTOPP_REMOVED
bool ValidateXMACC()
{
	typedef XMACC<MD5> XMACC_MD5;

	const byte keys[2][XMACC_MD5::KEYLENGTH]={
		{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb},
		{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98}};

	const word32 counters[2]={0xccddeeff, 0x76543210};

	const char *TestVals[7]={
		"",
		"a",
		"abc",
		"message digest",
		"abcdefghijklmnopqrstuvwxyz",
		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
		"12345678901234567890123456789012345678901234567890123456789012345678901234567890"};

	const byte output[2][7][XMACC_MD5::DIGESTSIZE]={
		{{0xcc,0xdd,0xef,0x00,0xfa,0x89,0x54,0x92,0x86,0x32,0xda,0x2a,0x3f,0x29,0xc5,0x52,0xa0,0x0d,0x05,0x13},
		{0xcc,0xdd,0xef,0x01,0xae,0xdb,0x8b,0x7b,0x69,0x71,0xc7,0x91,0x71,0x48,0x9d,0x18,0xe7,0xdf,0x9d,0x5a},
		{0xcc,0xdd,0xef,0x02,0x5e,0x01,0x2e,0x2e,0x4b,0xc3,0x83,0x62,0xc2,0xf4,0xe6,0x18,0x1c,0x44,0xaf,0xca},
		{0xcc,0xdd,0xef,0x03,0x3e,0xa9,0xf1,0xe0,0x97,0x91,0xf8,0xe2,0xbe,0xe0,0xdf,0xf3,0x41,0x03,0xb3,0x5a},
		{0xcc,0xdd,0xef,0x04,0x2e,0x6a,0x8d,0xb9,0x72,0xe3,0xce,0x9f,0xf4,0x28,0x45,0xe7,0xbc,0x80,0xa9,0xc7},
		{0xcc,0xdd,0xef,0x05,0x1a,0xd5,0x40,0x78,0xfb,0x16,0x37,0xfc,0x7a,0x1d,0xce,0xb4,0x77,0x10,0xb2,0xa0},
		{0xcc,0xdd,0xef,0x06,0x13,0x2f,0x11,0x47,0xd7,0x1b,0xb5,0x52,0x36,0x51,0x26,0xb0,0x96,0xd7,0x60,0x81}},
		{{0x76,0x54,0x32,0x11,0xe9,0xcb,0x74,0x32,0x07,0x93,0xfe,0x01,0xdd,0x27,0xdb,0xde,0x6b,0x77,0xa4,0x56},
		{0x76,0x54,0x32,0x12,0xcd,0x55,0x87,0x5c,0xc0,0x35,0x85,0x99,0x44,0x02,0xa5,0x0b,0x8c,0xe7,0x2c,0x68},
		{0x76,0x54,0x32,0x13,0xac,0xfd,0x87,0x50,0xc3,0x8f,0xcd,0x58,0xaa,0xa5,0x7e,0x7a,0x25,0x63,0x26,0xd1},
		{0x76,0x54,0x32,0x14,0xe3,0x30,0xf5,0xdd,0x27,0x2b,0x76,0x22,0x7f,0xaa,0x90,0x73,0x6a,0x48,0xdb,0x00},
		{0x76,0x54,0x32,0x15,0xfc,0x57,0x00,0x20,0x7c,0x9d,0xf6,0x30,0x6f,0xbd,0x46,0x3e,0xfb,0x8a,0x2c,0x60},
		{0x76,0x54,0x32,0x16,0xfb,0x0f,0xd3,0xdf,0x4c,0x4b,0xc3,0x05,0x9d,0x63,0x1e,0xba,0x25,0x2b,0xbe,0x35},
		{0x76,0x54,0x32,0x17,0xc6,0xfe,0xe6,0x5f,0xb1,0x35,0x8a,0xf5,0x32,0x7a,0x80,0xbd,0xb8,0x72,0xee,0xae}}};

	// Coverity finding, also see http://stackoverflow.com/a/34509163/608639.
	StreamState ss(std::cout);

	byte digest[XMACC_MD5::DIGESTSIZE];
	bool pass=true, fail;

	std::cout << "\nXMACC/MD5 validation suite running...\n";

	for (int k=0; k<2; k++)
	{
		XMACC_MD5 mac(keys[k], counters[k]);
		std::cout << "\nKEY: ";
		for (int j=0;j<XMACC_MD5::KEYLENGTH;j++)
			std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)keys[k][j];
		std::cout << "    COUNTER: 0x" << std::hex << counters[k] << std::endl << std::endl;
		for (int i=0;i<7;i++)
		{
			mac.Update((byte *)TestVals[i], strlen(TestVals[i]));
			mac.Final(digest);
			fail = std::memcmp(digest, output[k][i], XMACC_MD5::DIGESTSIZE) != 0
				 || !mac.VerifyDigest(output[k][i], (byte *)TestVals[i], strlen(TestVals[i]));
			pass = pass && !fail;
			std::cout << (fail ? "FAILED   " : "passed   ");
			for (int j=0;j<XMACC_MD5::DIGESTSIZE;j++)
				std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)digest[j];
			std::cout << "   \"" << TestVals[i] << '\"' << std::endl;
		}
	}

	return pass;
}
#endif

bool ValidateTTMAC()
{
	const byte key[TTMAC::KEYLENGTH]={
		0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,
		0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x01,0x23,0x45,0x67};

	const char *TestVals[8]={
		"",
		"a",
		"abc",
		"message digest",
		"abcdefghijklmnopqrstuvwxyz",
		"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
		"12345678901234567890123456789012345678901234567890123456789012345678901234567890"};

	const byte output[8][TTMAC::DIGESTSIZE]={
		{0x2d,0xec,0x8e,0xd4,0xa0,0xfd,0x71,0x2e,0xd9,0xfb,0xf2,0xab,0x46,0x6e,0xc2,0xdf,0x21,0x21,0x5e,0x4a},
		{0x58,0x93,0xe3,0xe6,0xe3,0x06,0x70,0x4d,0xd7,0x7a,0xd6,0xe6,0xed,0x43,0x2c,0xde,0x32,0x1a,0x77,0x56},
		{0x70,0xbf,0xd1,0x02,0x97,0x97,0xa5,0xc1,0x6d,0xa5,0xb5,0x57,0xa1,0xf0,0xb2,0x77,0x9b,0x78,0x49,0x7e},
		{0x82,0x89,0xf4,0xf1,0x9f,0xfe,0x4f,0x2a,0xf7,0x37,0xde,0x4b,0xd7,0x1c,0x82,0x9d,0x93,0xa9,0x72,0xfa},
		{0x21,0x86,0xca,0x09,0xc5,0x53,0x31,0x98,0xb7,0x37,0x1f,0x24,0x52,0x73,0x50,0x4c,0xa9,0x2b,0xae,0x60},
		{0x8a,0x7b,0xf7,0x7a,0xef,0x62,0xa2,0x57,0x84,0x97,0xa2,0x7c,0x0d,0x65,0x18,0xa4,0x29,0xe7,0xc1,0x4d},
		{0x54,0xba,0xc3,0x92,0xa8,0x86,0x80,0x6d,0x16,0x95,0x56,0xfc,0xbb,0x67,0x89,0xb5,0x4f,0xb3,0x64,0xfb},
		{0x0c,0xed,0x2c,0x9f,0x8f,0x0d,0x9d,0x03,0x98,0x1a,0xb5,0xc8,0x18,0x4b,0xac,0x43,0xdd,0x54,0xc4,0x84}};

	byte digest[TTMAC::DIGESTSIZE];
	bool pass=true, fail;
	std::ostringstream oss;

	oss << "\nTwo-Track-MAC validation suite running...\n";

	TTMAC mac(key, sizeof(key));
	for (unsigned int k = 0; k<COUNTOF(TestVals); k++)
	{
		mac.Update((byte *)TestVals[k], strlen(TestVals[k]));
		mac.Final(digest);
		fail = std::memcmp(digest, output[k], TTMAC::DIGESTSIZE) != 0
			|| !mac.VerifyDigest(output[k], (byte *)TestVals[k], strlen(TestVals[k]));
		pass = pass && !fail;
		oss << (fail ? "FAILED   " : "passed   ");
		for (int j=0;j<TTMAC::DIGESTSIZE;j++)
			oss << std::setw(2) << std::setfill('0') << std::hex << (int)digest[j];
		oss << "   \"" << TestVals[k] << '\"' << std::endl;
	}

	std::cout << oss.str();
	return true;
}

struct PBKDF_TestTuple
{
	byte purpose;
	unsigned int iterations;
	const char *hexPassword, *hexSalt, *hexDerivedKey;
};

bool TestPBKDF(KeyDerivationFunction &pbkdf, const PBKDF_TestTuple *testSet, size_t testSetSize)
{
	bool pass = true;

	for (size_t i=0; i<testSetSize; i++)
	{
		const PBKDF_TestTuple &tuple = testSet[i];

		std::string password, salt, derivedKey;
		StringSource(tuple.hexPassword, true, new HexDecoder(new StringSink(password)));
		StringSource(tuple.hexSalt, true, new HexDecoder(new StringSink(salt)));
		StringSource(tuple.hexDerivedKey, true, new HexDecoder(new StringSink(derivedKey)));

		double timeInSeconds = 0.0f;
		AlgorithmParameters params = MakeParameters("Purpose", (int)tuple.purpose)
		    (Name::Salt(), ConstByteArrayParameter(ConstBytePtr(salt), BytePtrSize(salt)))
		    ("Iterations", (int)tuple.iterations)("TimeInSeconds", timeInSeconds);

		SecByteBlock derived(derivedKey.size());
		pbkdf.DeriveKey(derived, derived.size(), ConstBytePtr(password), BytePtrSize(password), params);
		bool fail = std::memcmp(derived, derivedKey.data(), derived.size()) != 0;
		pass = pass && !fail;

		HexEncoder enc(new FileSink(std::cout));
		std::cout << (fail ? "FAILED   " : "passed   ");
		enc.Put(tuple.purpose);
		std::cout << " " << tuple.iterations;
		std::cout << " " << tuple.hexPassword << " " << tuple.hexSalt << " ";
		enc.Put(derived, derived.size());
		std::cout << std::endl;
	}

	return pass;
}

bool ValidatePBKDF()
{
	bool pass = true;

	{
	// from OpenSSL PKCS #12 Program FAQ v1.77, at http://www.drh-consultancy.demon.co.uk/test.txt
	PBKDF_TestTuple testSet[] =
	{
		{1, 1, "0073006D006500670000", "0A58CF64530D823F", "8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3"},
		{2, 1, "0073006D006500670000", "0A58CF64530D823F", "79993DFE048D3B76"},
		{1, 1, "0073006D006500670000", "642B99AB44FB4B1F", "F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966"},
		{2, 1, "0073006D006500670000", "642B99AB44FB4B1F", "C0A38D64A79BEA1D"},
		{3, 1, "0073006D006500670000", "3D83C0E4546AC140", "8D967D88F6CAA9D714800AB3D48051D63F73A312"},
		{1, 1000, "007100750065006500670000", "05DEC959ACFF72F7", "ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4"},
		{2, 1000, "007100750065006500670000", "05DEC959ACFF72F7", "11DEDAD7758D4860"},
		{1, 1000, "007100750065006500670000", "1682C0FC5B3F7EC5", "483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F"},
		{2, 1000, "007100750065006500670000", "1682C0FC5B3F7EC5", "9D461D1B00355C50"},
		{3, 1000, "007100750065006500670000", "263216FCC2FAB31C", "5EC4C7A80DF652294C3925B6489A7AB857C83476"}
	};

	PKCS12_PBKDF<SHA1> pbkdf;

	std::cout << "\nPKCS #12 PBKDF validation suite running...\n\n";
	pass = TestPBKDF(pbkdf, testSet, COUNTOF(testSet)) && pass;
	}

	{
	// from draft-ietf-smime-password-03.txt, at http://www.imc.org/draft-ietf-smime-password
	PBKDF_TestTuple testSet[] =
	{
		{0, 5, "70617373776f7264", "1234567878563412", "D1DAA78615F287E6"},
		{0, 500, "416C6C206E2D656E746974696573206D75737420636F6D6D756E69636174652077697468206F74686572206E2d656E74697469657320766961206E2D3120656E746974656568656568656573", "1234567878563412","6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"}
	};

	PKCS5_PBKDF2_HMAC<SHA1> pbkdf;

	std::cout << "\nPKCS #5 PBKDF2 validation suite running...\n\n";
	pass = TestPBKDF(pbkdf, testSet, COUNTOF(testSet)) && pass;
	}

	return pass;
}

struct HKDF_TestTuple
{
	const char *hexSecret, *hexSalt, *hexInfo, *hexExpected;
	size_t len;
};

bool TestHKDF(KeyDerivationFunction &kdf, const HKDF_TestTuple *testSet, size_t testSetSize)
{
	bool pass = true;

	for (size_t i=0; i<testSetSize; i++)
	{
		const HKDF_TestTuple &tuple = testSet[i];

		std::string secret, salt, info, expected;
		StringSource(tuple.hexSecret, true, new HexDecoder(new StringSink(secret)));
		StringSource(tuple.hexSalt ? tuple.hexSalt : "", true, new HexDecoder(new StringSink(salt)));
		StringSource(tuple.hexInfo ? tuple.hexInfo : "", true, new HexDecoder(new StringSink(info)));
		StringSource(tuple.hexExpected, true, new HexDecoder(new StringSink(expected)));
		SecByteBlock derived(expected.size());

		AlgorithmParameters params;
		if (tuple.hexSalt)
			params(Name::Salt(), ConstByteArrayParameter(ConstBytePtr(salt), BytePtrSize(salt)));
		if (tuple.hexSalt)
			params("Info", ConstByteArrayParameter(ConstBytePtr(info), BytePtrSize(info)));

		kdf.DeriveKey(derived, derived.size(), ConstBytePtr(secret), BytePtrSize(secret), params);

		bool fail = !VerifyBufsEqual(derived, ConstBytePtr(expected), BytePtrSize(expected));
		pass = pass && !fail;

		HexEncoder enc(new FileSink(std::cout));
		std::cout << (fail ? "FAILED   " : "passed   ");
		std::cout << " " << tuple.hexSecret << " ";
		std::cout << (tuple.hexSalt ? (strlen(tuple.hexSalt) ? tuple.hexSalt : "<0-LEN SALT>") : "<NO SALT>");
		std::cout << " ";
		std::cout << (tuple.hexInfo ? (strlen(tuple.hexInfo) ? tuple.hexInfo : "<0-LEN INFO>") : "<NO INFO>");
		std::cout << " ";
		enc.Put(derived, derived.size());
		std::cout << std::endl;
	}

	return pass;
}

bool ValidateHKDF()
{
	bool pass = true;

	{
	// SHA-1 from RFC 5869, Appendix A, https://tools.ietf.org/html/rfc5869
	const HKDF_TestTuple testSet[] =
	{
		// Test Case #4
		{"0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "085a01ea1b10f36933068b56efa5ad81 a4f14b822f5b091568a9cdd4f155fda2 c22e422478d305f3f896", 42},
		// Test Case #5
		{"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "0bd770a74d1160f7c9f12cd5912a06eb ff6adcae899d92191fe4305673ba2ffe 8fa3f1a4e5ad79f3f334b3b202b2173c 486ea37ce3d397ed034c7f9dfeb15c5e 927336d0441f4c4300e2cff0d0900b52 d3b4", 82},
		// Test Case #6
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "0ac1af7002b3d761d1e55298da9d0506 b9ae52057220a306e07b6b87e8df21d0 ea00033de03984d34918", 42},
		// Test Case #7
		{"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", NULLPTR, "", "2c91117204d745f3500d636a62f64f0 ab3bae548aa53d423b0d1f27ebba6f5e5 673a081d70cce7acfc48", 42}
	};

	HKDF<SHA1> hkdf;

	std::cout << "\nRFC 5869 HKDF(SHA-1) validation suite running...\n\n";
	pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass;
	}

	{
	// SHA-256 from RFC 5869, Appendix A, https://tools.ietf.org/html/rfc5869
	const HKDF_TestTuple testSet[] =
	{
		// Test Case #1
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "3cb25f25faacd57a90434f64d0362f2a 2d2d0a90cf1a5a4c5db02d56ecc4c5bf 34007208d5b887185865", 42},
		// Test Case #2
		{"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "b11e398dc80327a1c8e7f78c596a4934 4f012eda2d4efad8a050cc4c19afa97c 59045a99cac7827271cb41c65e590e09 da3275600c2f09b8367793a9aca3db71 cc30c58179ec3e87c14c01d5c1f3434f 1d87", 82},
		// Test Case #3
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "8da4e775a563c18f715f802a063c5a31 b8a11f5c5ee1879ec3454e5f3c738d2d 9d201395faa4b61a96c8", 42}
	};

	HKDF<SHA256> hkdf;

	std::cout << "\nRFC 5869 HKDF(SHA-256) validation suite running...\n\n";
	pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass;
	}

	{
	// SHA-512, Crypto++ generated, based on RFC 5869, https://tools.ietf.org/html/rfc5869
	const HKDF_TestTuple testSet[] =
	{
		// Test Case #0
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "832390086CDA71FB47625BB5CEB168E4 C8E26A1A16ED34D9FC7FE92C14815793 38DA362CB8D9F925D7CB", 42},
		// Test Case #0
		{"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "CE6C97192805B346E6161E821ED16567 3B84F400A2B514B2FE23D84CD189DDF1 B695B48CBD1C8388441137B3CE28F16A A64BA33BA466B24DF6CFCB021ECFF235 F6A2056CE3AF1DE44D572097A8505D9E 7A93", 82},
		// Test Case #0
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "F5FA02B18298A72A8C23898A8703472C 6EB179DC204C03425C970E3B164BF90F FF22D04836D0E2343BAC", 42},
		// Test Case #0
		{"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", NULLPTR, "", "1407D46013D98BC6DECEFCFEE55F0F90 B0C7F63D68EB1A80EAF07E953CFC0A3A 5240A155D6E4DAA965BB", 42}
	};

	HKDF<SHA512> hkdf;

	std::cout << "\nRFC 5869 HKDF(SHA-512) validation suite running...\n\n";
	pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass;
	}

	{
	// Whirlpool, Crypto++ generated, based on RFC 5869, https://tools.ietf.org/html/rfc5869
	const HKDF_TestTuple testSet[] =
	{
		// Test Case #0
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "0D29F74CCD8640F44B0DD9638111C1B5 766EFED752AF358109E2E7C9CD4A28EF 2F90B2AD461FBA0744D4", 42},
		// Test Case #0
		{"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "4EBE4FE2DCCEC42661699500BE279A99 3FED90351E19373B3926FAA3A410700B2 BBF77E254CF1451AE6068D64A0904D96 6F4FF25498445A501B88F50D21E3A68A8 90E09445DC5886DD00E7F4F7C58A5121 70", 82},
		// Test Case #0
		{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "110632D0F7AEFAC31771FC66C22BB346 2614B81E4B04BA7F2B662E0BD694F564 58615F9A9CB56C57ECF2", 42},
		// Test Case #0
		{"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" /*key*/, NULLPTR /*salt*/, "" /*info*/, "4089286EBFB23DD8A02F0C9DAA35D538 EB09CD0A8CBAB203F39083AA3E0BD313 E6F91E64F21A187510B0", 42}
	};

	HKDF<Whirlpool> hkdf;

	std::cout << "\nRFC 5869 HKDF(Whirlpool) validation suite running...\n\n";
	pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass;
	}

	return pass;
}

struct Scrypt_TestTuple
{
	const char * passwd;
	const char * salt;
	word64 n;
	word32 r;
	word32 p;
	const char * expect;
};

bool TestScrypt(KeyDerivationFunction &pbkdf, const Scrypt_TestTuple *testSet, size_t testSetSize)
{
	bool pass = true;

	for (size_t i=0; i<testSetSize; i++)
	{
		const Scrypt_TestTuple &tuple = testSet[i];

		std::string password(tuple.passwd), salt(tuple.salt), expect;
		StringSource(tuple.expect, true, new HexDecoder(new StringSink(expect)));

		AlgorithmParameters params = MakeParameters("Cost", (word64)tuple.n)
			("BlockSize", (word64)tuple.r)("Parallelization", (word64)tuple.p)
			(Name::Salt(), ConstByteArrayParameter(ConstBytePtr(salt), BytePtrSize(salt)));

		SecByteBlock derived(expect.size());
		pbkdf.DeriveKey(derived, derived.size(), ConstBytePtr(password), BytePtrSize(password), params);
		bool fail = std::memcmp(derived, expect.data(), expect.size()) != 0;
		pass = pass && !fail;

		if (password.empty()) {password="\"\"";}
		if (salt.empty()) {salt="\"\"";}

		HexEncoder enc(new FileSink(std::cout));
		std::cout << (fail ? "FAILED   " : "passed   ");
		std::cout << " " << password << " " << salt << " ";
		std::cout << " " << tuple.n << " " << tuple.r;
		std::cout << " " << tuple.p << " ";
		enc.Put(derived, derived.size());
		std::cout << std::endl;
	}

	return pass;
}

bool ValidateScrypt()
{
	bool pass = true;

	// https://tools.ietf.org/html/rfc7914
	const Scrypt_TestTuple testSet[] =
	{
			{ "", "", 16, 1, 1, "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906"},
			{ "password", "NaCl", 1024, 8, 16, "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"},
			{ "pleaseletmein", "SodiumChloride", 16384, 8, 1, "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887"},
#ifndef CRYPTOPP_DEBUG
			// This one takes too long in debug builds
			// { "pleaseletmein", "SodiumChloride", 1048576, 8, 1, "2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4"}
#endif
	};

	Scrypt pbkdf;

	std::cout << "\nRFC 7914 Scrypt validation suite running...\n\n";
	pass = TestScrypt(pbkdf, testSet, COUNTOF(testSet)) && pass;

	return pass;
}

struct Poly1305_TestTuples
{
	const char *key, *message, *nonce, *digest;
	size_t klen, mlen, nlen, dlen;
};

bool ValidatePoly1305()
{
	std::cout << "\nPoly1305 validation suite running...\n\n";
	bool fail, pass = true;

	{
		fail = (Poly1305<AES>::StaticAlgorithmName() != "Poly1305(AES)");
		std::cout << (fail ? "FAILED   " : "passed   ") << "algorithm name\n";
		pass = pass && !fail;
	}

	// Test data from http://cr.yp.to/mac/poly1305-20050329.pdf
	const Poly1305_TestTuples tests[] =
	{
		// Appendix B, Test 1
		{
			"\xec\x07\x4c\x83\x55\x80\x74\x17\x01\x42\x5b\x62\x32\x35\xad\xd6"   // Key
			"\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00",
			"\xf3\xf6",                                                          // Message
			"\xfb\x44\x73\x50\xc4\xe8\x68\xc5\x2a\xc3\x27\x5c\xf9\xd4\x32\x7e",  // Nonce
			"\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde",  // Digest
			32, 2, 16, 16
		},
		// Appendix B, Test 2
		{
			"\x75\xde\xaa\x25\xc0\x9f\x20\x8e\x1d\xc4\xce\x6b\x5c\xad\x3f\xbf"   // Key
			"\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc",
			"",                                                                  // Message
			"\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc",  // Nonce
			"\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7",  // Digest
			32, 0, 16, 16
		},
		// Appendix B, Test 3
		{
			"\x6a\xcb\x5f\x61\xa7\x17\x6d\xd3\x20\xc5\xc1\xeb\x2e\xdc\xdc\x74"   // Key
			"\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08",
			"\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24"   // Message
			"\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36",
			"\xae\x21\x2a\x55\x39\x97\x29\x59\x5d\xea\x45\x8b\xc6\x21\xff\x0e",  // Nonce
			"\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe",  // Digest
			32, 32, 16, 16
		},
		// Appendix B, Test 4
		{
			"\xe1\xa5\x66\x8a\x4d\x5b\x66\xa5\xf6\x8c\xc5\x42\x4e\xd5\x98\x2d"   // Key
			"\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07",
			"\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1"   // Message
			"\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0"
			"\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67"
			"\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9",
			"\x9a\xe8\x31\xe7\x43\x97\x8d\x3a\x23\x52\x7c\x71\x28\x14\x9e\x3a",  // Nonce
			"\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b",  // Digest
			32, 63, 16, 16
		}
	};

	unsigned int count = 0;
	byte digest[Poly1305<AES>::DIGESTSIZE];

	// Positive tests
	for (size_t i=0; i<COUNTOF(tests); ++i)
	{
		Poly1305<AES> poly1305((const byte*)tests[i].key, tests[i].klen);
		poly1305.Resynchronize((const byte*)tests[i].nonce, (int)tests[i].nlen);
		poly1305.Update((const byte*)tests[i].message, tests[i].mlen);
		poly1305.Final(digest);

		fail = std::memcmp(digest, tests[i].digest, tests[i].dlen) != 0;
		if (fail)
		{
			std::cout << "FAILED   " << "Poly1305 test set " << count << std::endl;
		}

		count++;
		pass = pass && !fail;
	}

	// Positive tests
	for (size_t i=0; i<COUNTOF(tests); ++i)
	{
		Poly1305<AES> poly1305((const byte*)tests[i].key, tests[i].klen,(const byte*)tests[i].nonce, (int)tests[i].nlen);
		poly1305.Update((const byte*)tests[i].message, tests[i].mlen);
		poly1305.Final(digest);

		fail = std::memcmp(digest, tests[i].digest, tests[i].dlen) != 0;
		if (fail)
		{
			std::cout << "FAILED   " << "Poly1305 test set " << count << std::endl;
		}

		count++;
		pass = pass && !fail;
	}

	// Negative tests
	for (size_t i=0; i<COUNTOF(tests); ++i)
	{
		Poly1305<AES> poly1305((const byte*)tests[i].key, tests[i].klen);
		poly1305.Resynchronize((const byte*)tests[i].nonce, (int)tests[i].nlen);
		poly1305.Update((const byte*)tests[i].message, tests[i].mlen);
		poly1305.Final(digest);

		unsigned int next = (i+1) % COUNTOF(tests);
		fail = std::memcmp(digest, tests[next].digest, tests[next].dlen) == 0;
		if (fail)
		{
			std::cout << "FAILED   " << "Poly1305 test set " << count << std::endl;
		}

		count++;
		pass = pass && !fail;
	}

	std::cout << (!pass ? "FAILED   " : "passed   ") << count << " message authentication codes" << std::endl;

	return pass;
}

bool ValidateSipHash()
{
	std::cout << "\nSipHash validation suite running...\n\n";
	bool fail, pass = true, pass1=true, pass2=true, pass3=true, pass4=true;

	{
		fail = (SipHash<2,4>::StaticAlgorithmName() != "SipHash-2-4");
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-2-4 algorithm name\n";
		pass = pass && !fail;

		fail = (SipHash<2,4, false>::DIGESTSIZE != 8);
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-2-4 64-bit digest size\n";
		pass = pass && !fail;

		fail = (SipHash<2,4, true>::DIGESTSIZE != 16);
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-2-4 128-bit digest size\n";
		pass = pass && !fail;

		fail = (SipHash<4,8>::StaticAlgorithmName() != "SipHash-4-8");
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-4-8 algorithm name\n";
		pass = pass && !fail;

		fail = (SipHash<4,8, false>::DIGESTSIZE != 8);
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-4-8 64-bit digest size\n";
		pass = pass && !fail;

		fail = (SipHash<4,8, true>::DIGESTSIZE != 16);
		std::cout << (fail ? "FAILED   " : "passed   ") << "SipHash-4-8 128-bit digest size\n";
		pass = pass && !fail;
	}

	// Siphash-2-4, 64-bit MAC
	{
		const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
		SipHash<2,4, false> hash(key, 16);
		byte digest[SipHash<2,4, false>::DIGESTSIZE];

		hash.Update((const byte*)"", 0);
		hash.Final(digest);
		fail = std::memcmp("\x31\x0E\x0E\xDD\x47\xDB\x6F\x72", digest, COUNTOF(digest)) != 0;
		pass1 = !fail && pass1;

		hash.Update((const byte*)"\x00", 1);
		hash.Final(digest);
		fail = std::memcmp("\xFD\x67\xDC\x93\xC5\x39\xF8\x74", digest, COUNTOF(digest)) != 0;
		pass1 = !fail && pass1;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7);
		hash.Final(digest);
		fail = std::memcmp("\x37\xD1\x01\x8B\xF5\x00\x02\xAB", digest, COUNTOF(digest)) != 0;
		pass1 = !fail && pass1;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8);
		hash.Final(digest);
		fail = std::memcmp("\x62\x24\x93\x9A\x79\xF5\xF5\x93", digest, COUNTOF(digest)) != 0;
		pass1 = !fail && pass1;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9);
		hash.Final(digest);
		fail = std::memcmp("\xB0\xE4\xA9\x0B\xDF\x82\x00\x9E", digest, COUNTOF(digest)) != 0;
		pass1 = !fail && pass1;

		std::cout << (pass1 ? "passed   " : "FAILED   ") << "SipHash-2-4 64-bit MAC\n";
		pass = pass1 && pass;
	}

	// Siphash-2-4, 128-bit MAC
	{
		const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
		SipHash<2,4, true> hash(key, 16);
		byte digest[SipHash<2,4, true>::DIGESTSIZE];

		hash.Update((const byte*)"", 0);
		hash.Final(digest);
		fail = std::memcmp("\xA3\x81\x7F\x04\xBA\x25\xA8\xE6\x6D\xF6\x72\x14\xC7\x55\x02\x93", digest, COUNTOF(digest)) != 0;
		pass3 = !fail && pass3;

		hash.Update((const byte*)"\x00", 1);
		hash.Final(digest);
		fail = std::memcmp("\xDA\x87\xC1\xD8\x6B\x99\xAF\x44\x34\x76\x59\x11\x9B\x22\xFC\x45", digest, COUNTOF(digest)) != 0;
		pass3 = !fail && pass3;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7);
		hash.Final(digest);
		fail = std::memcmp("\xA1\xF1\xEB\xBE\xD8\xDB\xC1\x53\xC0\xB8\x4A\xA6\x1F\xF0\x82\x39", digest, COUNTOF(digest)) != 0;
		pass3 = !fail && pass3;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8);
		hash.Final(digest);
		fail = std::memcmp("\x3B\x62\xA9\xBA\x62\x58\xF5\x61\x0F\x83\xE2\x64\xF3\x14\x97\xB4", digest, COUNTOF(digest)) != 0;
		pass3 = !fail && pass3;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9);
		hash.Final(digest);
		fail = std::memcmp("\x26\x44\x99\x06\x0A\xD9\xBA\xAB\xC4\x7F\x8B\x02\xBB\x6D\x71\xED", digest, COUNTOF(digest)) != 0;
		pass3 = !fail && pass3;

		std::cout << (pass3 ? "passed   " : "FAILED   ") << "SipHash-2-4 128-bit MAC\n";
		pass = pass3 && pass;
	}

	// Siphash-4-8, 64-bit MAC
	{
		const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
		SipHash<4, 8, false> hash(key, 16);
		byte digest[SipHash<4, 8, false>::DIGESTSIZE];

		hash.Update((const byte*)"", 0);
		hash.Final(digest);
		fail = std::memcmp("\x41\xDA\x38\x99\x2B\x05\x79\xC8", digest, COUNTOF(digest)) != 0;
		pass2 = !fail && pass2;

		hash.Update((const byte*)"\x00", 1);
		hash.Final(digest);
		fail = std::memcmp("\x51\xB8\x95\x52\xF9\x14\x59\xC8", digest, COUNTOF(digest)) != 0;
		pass2 = !fail && pass2;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7);
		hash.Final(digest);
		fail = std::memcmp("\x47\xD7\x3F\x71\x5A\xBE\xFD\x4E", digest, COUNTOF(digest)) != 0;
		pass2 = !fail && pass2;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8);
		hash.Final(digest);
		fail = std::memcmp("\x20\xB5\x8B\x9C\x07\x2F\xDB\x50", digest, COUNTOF(digest)) != 0;
		pass2 = !fail && pass2;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9);
		hash.Final(digest);
		fail = std::memcmp("\x36\x31\x9A\xF3\x5E\xE1\x12\x53", digest, COUNTOF(digest)) != 0;
		pass2 = !fail && pass2;

		std::cout << (pass2 ? "passed   " : "FAILED   ") << "SipHash-4-8 64-bit MAC\n";
		pass = pass2 && pass;
	}

	// Siphash-4-8, 128-bit MAC
	{
		const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
		SipHash<4, 8, true> hash(key, 16);
		byte digest[SipHash<4, 8, true>::DIGESTSIZE];

		hash.Update((const byte*)"", 0);
		hash.Final(digest);
		fail = std::memcmp("\x1F\x64\xCE\x58\x6D\xA9\x04\xE9\xCF\xEC\xE8\x54\x83\xA7\x0A\x6C", digest, COUNTOF(digest)) != 0;
		pass4 = !fail && pass4;

		hash.Update((const byte*)"\x00", 1);
		hash.Final(digest);
		fail = std::memcmp("\x47\x34\x5D\xA8\xEF\x4C\x79\x47\x6A\xF2\x7C\xA7\x91\xC7\xA2\x80", digest, COUNTOF(digest)) != 0;
		pass4 = !fail && pass4;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7);
		hash.Final(digest);
		fail = std::memcmp("\xED\x00\xE1\x3B\x18\x4B\xF1\xC2\x72\x6B\x8B\x54\xFF\xD2\xEE\xE0", digest, COUNTOF(digest)) != 0;
		pass4 = !fail && pass4;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8);
		hash.Final(digest);
		fail = std::memcmp("\xA7\xD9\x46\x13\x8F\xF9\xED\xF5\x36\x4A\x5A\x23\xAF\xCA\xE0\x63", digest, COUNTOF(digest)) != 0;
		pass4 = !fail && pass4;

		hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9);
		hash.Final(digest);
		fail = std::memcmp("\x9E\x73\x14\xB7\x54\x5C\xEC\xA3\x8B\x9A\x55\x49\xE4\xFB\x0B\xE8", digest, COUNTOF(digest)) != 0;
		pass4 = !fail && pass4;

		std::cout << (pass4 ? "passed   " : "FAILED   ") << "SipHash-4-8 128-bit MAC\n";
		pass = pass4 && pass;
	}

	return pass;
}

struct BLAKE2_TestTuples
{
	const char *key, *message, *digest;
	size_t klen, mlen, dlen;
};

bool ValidateBLAKE2s()
{
	std::cout << "\nBLAKE2s validation suite running...\n\n";
	bool fail, pass = true;

	{
		fail = strcmp(BLAKE2s::StaticAlgorithmName(), "BLAKE2s") != 0;
		std::cout << (fail ? "FAILED   " : "passed   ") << "algorithm name\n";
		pass = pass && !fail;
	}

	const BLAKE2_TestTuples tests[] = {
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x8F\x38",
	        0, 0, 2
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x36\xE9\xD2\x46",
	        0, 0, 4
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\xEF\x2A\x8B\x78\xDD\x80\xDA\x9C",
	        0, 0, 8
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x64\x55\x0D\x6F\xFE\x2C\x0A\x01\xA1\x4A\xBA\x1E\xAD\xE0\x20\x0C",
	        0, 0, 16
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x69\x21\x7A\x30\x79\x90\x80\x94\xE1\x11\x21\xD0\x42\x35\x4A\x7C\x1F\x55\xB6\x48\x2C\xA1\xA5\x1E\x1B\x25\x0D\xFD\x1E\xD0\xEE\xF9",
	        0, 0, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x25\xEC\xB2\xF6\xA7\x81\x82\x57\x5D\x4B\xD7\x02\x72\x6D\xE1\x82\xBB\x1E\x21\xA8\x5D\x51\x34\xAD\xA2\x25\x8D\x7E\x21\x38\x03\xA7",
	        0, 15, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xD4\x1C\x69\x87\x29\x7E\xDE\x4F\x08\x9B\x66\x9B\xC7\x0E\x62\xB9\xFA\xFA\x1C\x37\xCC\x31\x29\x22\xE0\xEA\x63\xE2\xE5\x85\xAA\x9F",
	        0, 16, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE0\xAD\xF2\xCC\x1F\x1F\x55\x3A\xE6\xC3\xCD\x3D\xF7\x68\xEA\x66\x9C\x32\xBE\x1D\x37\xF9\xA2\x61\xD4\x4F\x45\x26\x69\xD0\xD3\xA4",
	        0, 17, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x10\x42\x65\x1C\x86\x15\xC4\x87\x69\x41\x19\x1F\xB6\xD5\xC5\x1D\xEB\x4C\xA1\x8C\xAF\xEF\xEB\x79\x69\x62\x87\x0D\x6A\x5D\xEE\x20",
	        0, 31, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEA\xB1\xC5\xDD\xDF\xB5\x7C\x48\xC5\xB0\xB3\xF5\xBE\x5B\x47\x6D\xBB\xF5\xA3\x5C\x21\xD3\xDD\x94\x13\xA1\x04\xB8\x14\xF9\x2D\x4B",
	        0, 32, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x7E\x82\x07\x49\x14\x62\x11\x96\xC5\xE8\xF3\xCB\x0F\x21\x7B\x37\xAE\x9B\x64\x58\xF4\x66\x01\xB9\x21\x23\xAC\x48\x64\x30\x83\x8F",
	        0, 33, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x90\xB5\xA2\x5E\x8E\xA8\xA0\xC8\x74\x85\xAE\x18\x08\x9D\x92\xEB\x14\x5A\x5D\x4E\x2C\x60\x7B\xCB\x4B\x94\xD1\x0F\xAE\x59\x33\xC1",
	        0, 63, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x71\x27\x28\x45\x9E\x67\xD7\xED\xB7\xAE\xFA\x88\xFF\x5C\x7E\x7B\x5D\xA9\x94\xA1\xC3\xB1\x7B\x64\xFB\xC1\x4E\x47\xCA\xDA\x45\xDD",
	        0, 64, 32
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x58\x72\x3B\xB1\xBE\x18\x33\x12\x31\x5E\x6E\xF7\xF2\xB1\x84\x60\x97\x2C\x19\xD3\x01\xAF\x42\x00\xAB\xDB\x04\x26\xFC\xB0\xC1\xF8",
	        0, 65, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x9A\xD4\x81\xEF\x81\x6C\xAC\xB6\x59\x35\x8E\x6D\x6B\x73\xF1\xE5\xAC\x71\xD6\x6E\x8B\x12\x6B\x73\xD9\xD9\x7D\x2F\xA7\xA4\x61\xB4",
	        15, 0, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x61\x8C\xBE\x19\x4B\x28\xDC\xA3\x8B\xE5\x1A\x79\x37\x45\xB4\x66\x3D\xF1\x9D\xB5\x8F\xFF\xEF\xC4\x5D\x37\x82\x25\x93\xEB\xE2\x93",
	        15, 15, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF3\xEC\x81\x61\x44\x5C\x6E\x2E\xE6\x52\x6A\xCA\x5F\xD9\x25\x74\x2A\x33\xB9\x1F\xEF\x0F\x7E\x54\x4F\x50\xC2\xFB\x04\x3C\x52\xD2",
	        15, 16, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF4\x81\x43\x6E\x2F\x4C\x5D\x09\x21\x73\x24\xDA\xA6\x23\x9E\xFD\xF8\x82\xCE\x0E\x3E\x4C\xB4\x17\xCC\x27\xCD\x1A\xAE\x90\x9B\x94",
	        15, 17, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x99\x5E\x74\x8E\x96\xFE\xC0\x39\x5B\x73\xA3\xC0\x4E\xC7\xF7\xBE\x89\x83\xCD\x18\x24\x60\x60\x7B\xBC\xF5\x50\xF5\x84\xD1\x71\x6B",
	        15, 31, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x21\x6E\xB9\xE2\xE4\xAF\x94\x5F\x6A\xA3\xD2\xCA\x25\x72\xFB\x8F\xDB\x95\x2F\xAC\x1C\x69\xC1\x26\x28\x31\x63\x16\x25\xA5\x2C\xF8",
	        15, 32, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE3\x71\x9F\xD8\xAE\x68\xC8\xC4\x5D\x17\xDD\x21\x33\xBB\xE1\x61\x51\x22\xC2\x3B\x00\x6E\xDD\x66\x7E\x2A\x0A\x6B\x77\xA9\x0B\x8D",
	        15, 33, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xD3\xF8\x5F\x1B\xBE\x9C\x53\xCB\x7F\x5F\x5F\x62\x4D\x06\x36\x8F\xF8\x15\xA7\xF5\xEB\x77\xC6\xC5\xB4\x81\x15\x01\x82\x8D\x9D\x40",
	        15, 63, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xBF\xA3\xDA\x09\xF9\xDE\x1B\xE6\x57\x4B\x55\x82\x85\x69\x79\xA1\x89\xD6\xF4\x15\x8B\x03\xFA\xAC\x6E\x00\x80\x26\xF1\x6B\xA1\x28",
	        15, 64, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x77\x45\xEA\x51\x24\x46\x53\x19\x6F\xE4\xED\x6B\x54\x5C\x9B\x95\x88\xF5\xD4\x2B\x4C\x3E\xE6\xB7\xA1\xA3\x9F\xC4\x3A\x27\x1E\x45",
	        15, 65, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\xFD\x61\x6D\xA6\x8E\xEF\x10\x24\x16\xC7\xBD\x7D\xC8\xCA\xF8\x2B\x3D\x92\x7B\xCB\xDD\x06\x8E\x7C\xCA\xA7\x72\x76\xCE\x6C\x8C\xD4",
	        16, 0, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x10\x18\x97\x28\xFB\x05\x1D\xA0\xA8\xD6\x8F\x1C\xAD\x81\xFC\x7C\xA2\x6D\x41\x4B\xAA\x0C\x2A\x95\xB7\xF4\xEF\x9A\x67\xB5\x26\x5F",
	        16, 15, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x9E\x3B\x50\xF3\xB5\xF4\xC9\xB3\x57\x03\x74\xF1\xB3\xA0\x4B\x3C\xC1\x71\xB4\x30\x42\xE4\x65\x90\xE5\xE2\x8A\x4D\xBA\xCD\xB1\x9F",
	        16, 16, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x69\x70\x88\xAB\x61\x39\x46\xEA\x3B\xEB\x98\x98\x78\xCD\x8E\xF1\xB5\x7E\x81\xFC\x42\x7D\x46\xB8\xDA\x85\xD2\xEB\xB8\x56\xE4\xAC",
	        16, 17, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xD2\xDA\xAC\x63\x09\xF1\x81\xBB\xCC\x06\x0D\xCC\xB8\xFA\x67\x08\x14\xD4\x6A\x50\xD7\x4F\xBF\x3B\x4A\x2E\x39\x4D\x45\x55\x27\x2F",
	        16, 31, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEB\xB0\xF3\x27\xC3\xC4\x35\x97\x4F\x89\x73\x5A\x4D\xEB\xBB\x4C\x7C\xE9\x0C\x3E\x13\xEB\x07\x83\x74\x67\x0A\x86\xA7\xF4\xA8\x73",
	        16, 32, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xC8\x96\xC3\x3A\x26\x77\x02\x84\x5D\x95\x1B\x0D\x9F\x5C\x07\xC5\x6D\x21\x5D\x7E\x20\xF1\x2F\xE0\x45\xE3\x50\x42\x9D\x58\xB0\xEA",
	        16, 33, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x8A\x3C\x9F\xA4\xAC\x78\x82\xA7\x08\x76\xB9\xE1\xED\x22\x9B\x43\x45\xF4\xD4\x01\x76\xC4\xED\x5D\xA4\x5A\x41\xDE\x28\xB8\x09\x6C",
	        16, 63, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x2D\x0C\x97\xBE\xD2\xF2\x13\x40\xB9\xC8\x15\x91\x6A\x55\x86\x7A\x43\xB1\xFD\xC7\x04\x08\x1B\x58\x37\x09\x12\x80\x40\x99\x7C\xED",
	        16, 64, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF7\xC0\x08\xE1\x31\x52\x9B\x71\x87\x51\xCF\xFF\x8B\x08\xA3\x14\x32\x08\x06\x8C\x22\xAD\x83\x97\x71\x95\xC5\x2C\xFC\x66\xA4\xAD",
	        16, 65, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\xD0\xCE\x8E\x8D\xA0\xBA\xA4\x26\x0E\xD3\x1F\xD1\x7B\x78\xE6\x18\x15\xC6\xFF\xD8\x5A\xDB\x41\x8A\xE7\x36\xF0\xE7\xB9\x87\x2B\x6A",
	        17, 0, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xCB\xE4\x63\xEB\x6B\x24\x6C\x08\x55\x84\x36\x30\x8E\xFA\xC1\x6B\x97\x43\xD7\x1F\x1F\x3E\x96\xBA\x7E\x87\xF2\x42\x3E\xF5\x69\x5E",
	        17, 15, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEF\x39\x55\x9D\x92\x20\xDC\xB6\x8C\x21\x79\xD6\x7C\x51\xB7\x36\xAC\x4E\xFC\xA1\xDE\x66\xC7\xED\x40\xBF\x23\x15\xD1\x25\x82\x4B",
	        17, 16, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE3\x3E\x44\x7B\xA2\x7F\x69\x21\x09\x57\x79\x72\xE7\x4B\xE0\xC7\xCD\x54\xDC\xCD\x55\x60\x75\x61\x82\x66\xD7\x5B\x6F\x60\xDD\x73",
	        17, 17, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA9\xC4\x29\x2F\x5B\x49\x9A\xE0\x71\xE7\xFD\x65\x98\x53\x42\xC0\xC0\xF1\x75\xBC\xB5\x7B\x5C\xA1\x61\xFC\x8B\x45\x44\x54\xEC\x06",
	        17, 31, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x29\x60\xBD\x05\x28\xEA\xF1\xA9\x43\xEF\x2D\x87\xC7\xB5\x27\x47\x33\xBA\xC8\x0C\x9F\x1C\xF5\x72\x62\x4C\xA7\x9E\x10\x23\x66\x76",
	        17, 32, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE2\xF1\x33\x23\x9D\xD8\xBC\x60\x1F\xB7\xD8\x21\xF5\x13\x98\xE2\x5C\x24\x0E\xC0\x60\x18\xB4\x0B\x93\xF1\x04\x25\xC5\xEC\x20\x14",
	        17, 33, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEB\x4F\x8D\xB3\xF5\x03\x72\x55\x72\xCE\xF3\x91\x22\xCD\xEA\x5A\xC4\x9A\xD0\x42\xE1\xC4\x62\x90\xCE\x11\x9E\xFD\x11\xDB\xCA\x23",
	        17, 63, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xB5\x9A\xA7\x74\xDA\xB8\xDE\x5C\xBB\xC3\x5A\xFC\xF0\xD7\xAF\x51\x1E\x0F\x05\x45\xDB\xDA\xB7\xA4\xA6\x52\xB2\x9E\x0E\x23\x14\x3D",
	        17, 64, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x69\xA2\x95\x6C\x87\xED\x22\x76\x0A\x53\x75\x6D\x28\xF4\xCD\xC5\xF7\xF9\x88\x51\x73\xA7\xD9\x44\x0C\x96\xB1\x5F\xE5\x57\xFE\xE3",
	        17, 65, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x39\x4A\xB9\x85\xDD\xFF\x59\x59\x84\x5A\xF7\x54\xD6\xFC\x19\xFB\x94\x0E\xAE\xA4\xEA\x70\x54\x3E\x0D\x7E\x9D\xC7\x8A\x22\x77\x3B",
	        31, 0, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x1B\x46\x57\xC0\x48\x26\x7B\xC6\x17\xEC\xD5\x76\x89\xEE\x81\xE5\x5B\xE0\xAC\xCE\xB7\x5D\x33\x2A\xAF\xB6\xE2\xF6\xC0\xBB\x93\xE6",
	        31, 15, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x53\xB3\x3A\x58\x98\xD2\x0D\x25\x61\x5A\x0C\xF5\x74\x7F\x44\x2F\x51\x70\x31\x66\x5E\x41\x5E\xBC\xF5\xF0\x03\x12\x98\x12\x90\xCC",
	        31, 16, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x0B\x2C\x2A\x74\x72\x12\x18\xE1\xCE\xCD\x8A\x7E\xFC\xCE\x8D\x57\xBE\x42\x1A\xCC\xA2\x20\x24\x33\xC5\x1E\x31\x54\x1F\xB6\x45\xBD",
	        31, 17, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEF\x13\x95\xD4\x42\xC9\x9A\x04\xFE\xF0\x11\xE9\x72\xA9\x37\x74\x3E\x14\xC4\x4C\x58\x0C\xAC\x81\x4A\x75\x73\x35\x05\xC0\x81\x32",
	        31, 31, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x0D\x35\xCF\x7F\x82\x08\x1E\x1B\xE9\x1E\x75\xE1\x96\x05\x9F\xBD\x63\x94\x8E\xE0\x71\xEF\x53\xDE\x79\xC6\x68\x21\xD6\x8A\x5A\xE4",
	        31, 32, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x74\x0D\xCB\x50\x59\x59\xB9\x48\x52\x2B\x0B\x2A\x1F\xFC\x4F\x12\xF5\x9F\x49\x11\xED\x43\x61\xA6\x38\x8D\xF9\x35\x5C\xCD\x18\xBB",
	        31, 33, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xDD\x48\xE5\xE8\x86\x8E\x61\xFF\x8A\x85\xC6\x5A\xB8\x5A\x32\xD2\x2A\x9C\xA2\xC8\xDC\xB9\xD6\x0A\x44\xD3\xF1\xB4\x8B\x5B\xD3\x80",
	        31, 63, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x81\xEF\xAD\x79\x16\xE4\x29\x02\xDB\x89\x8D\xF2\xA4\x6D\xB4\xC4\x2A\x8C\xC6\x7E\xDE\x9B\xF7\x63\xB2\x10\xED\x15\xED\x0A\x0E\x3C",
	        31, 64, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEB\x54\xC4\x8A\x8F\x92\x53\x4D\xDF\x1D\x78\xCA\x98\x38\xF9\x10\xE4\x05\xCD\x6D\xB6\x82\x3B\x76\xB7\x82\x3A\xD2\x20\x77\xD4\x89",
	        31, 65, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x18\xE3\xCE\x19\x98\x7B\xA5\x0B\x30\xDD\x14\x4C\x16\xF2\x26\x55\xEB\xA3\x14\x09\xD6\x62\x10\xBC\x38\xBB\xC1\x4B\x5D\xAB\x05\x19",
	        32, 0, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x10\x9D\x6C\xB3\x37\x9C\x9E\x2B\xC9\x1C\xF9\x79\x7A\x46\xEA\xFA\x78\x5C\xA1\x54\x83\xBD\xC2\x67\x31\xFA\x66\xAC\x5D\x4C\xE7\xAB",
	        32, 15, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x76\x83\x9A\x8F\xBC\x20\x81\xD6\x09\x5C\x97\x46\xD3\xD6\xA4\xC4\xC1\x17\x8E\x3B\x14\xFC\xFD\x8F\x72\x20\xEF\xC6\x0B\xD3\xFF\x42",
	        32, 16, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEA\x0C\x05\xE6\x8F\xD6\xA6\xA1\xD9\xFC\xDA\x3C\xCB\x49\x02\xA5\xF9\x5D\x80\x9E\x89\xF6\xA2\x15\x74\x48\x84\x87\x77\x47\x6D\xBB",
	        32, 17, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x98\x79\xD8\x91\x48\xB3\x12\x10\xE8\x49\x73\x38\x1B\xFA\x6C\xCA\x85\x59\xF9\xF9\xFE\xD3\xF2\x98\x9E\x9D\x5C\xE8\x1E\x59\xB3\x46",
	        32, 31, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xC7\x41\x7E\x23\xDD\x7D\xB0\x84\xCA\x64\x26\x5A\xE0\x98\xD7\xF2\x29\xE4\x4C\x88\xC9\xF9\x15\x00\x19\x73\xC7\xCF\x95\xF5\x30\x68",
	        32, 32, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x0F\xDA\x45\x55\xAC\x8F\xB0\x17\x1D\xF2\x41\x54\xFB\x41\x26\x16\x0C\x00\x84\x49\x3D\x54\xAE\x9F\x13\xD4\xE5\x11\x2B\x42\xB5\xF5",
	        32, 33, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF1\x1B\x54\x05\xCE\x3A\xEB\xA1\x1B\x49\x99\x43\xBF\x2C\x73\x10\x0E\x35\x6B\xEA\x40\xAC\xE5\xBC\xD8\xD5\xB0\xAE\xB2\x8E\xFB\x05",
	        32, 63, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEA\xAF\xA4\xBE\xD6\x9D\x98\x73\x5E\xDF\xFC\x35\xFD\xB8\x26\x18\xAC\x15\x9E\x2B\xB2\xF9\x36\xEC\x51\x58\x1E\xD8\x53\xB7\x11\x10",
	        32, 64, 32
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xC3\x0A\xE0\xAB\xFA\x38\x3C\x3F\xBC\x44\xD3\x2A\x4F\xC8\xFA\x86\xF2\x15\x9E\x83\x75\x65\xE4\x78\x63\xED\xEF\x31\x79\xEC\x00\x21",
	        32, 65, 32
	    }
	};

	{
		byte digest[BLAKE2s::DIGESTSIZE];
		for (size_t i=0; i<COUNTOF(tests); ++i)
		{
			// the condition is written in a way which for non-default digest sizes
			// tests the BLAKE2_Base(bool treeMode, unsigned int digestSize) constructor.
			// See https://github.com/weidai11/cryptopp/issues/415
			if (tests[i].dlen < BLAKE2s::DIGESTSIZE && tests[i].key == NULLPTR)
			{
				BLAKE2s blake2s(false, (unsigned int)tests[i].dlen);
				blake2s.Update((const byte*)tests[i].message, tests[i].mlen);
				blake2s.Final(digest);
			}
			else
			{
				BLAKE2s blake2s((const byte*)tests[i].key, tests[i].klen, NULLPTR, 0, NULLPTR, 0, false, (unsigned int)tests[i].dlen);
				blake2s.Update((const byte*)tests[i].message, tests[i].mlen);
				blake2s.Final(digest);
			}

			fail = std::memcmp(digest, tests[i].digest, tests[i].dlen) != 0;
			if (fail)
			{
				std::cout << "FAILED   " << "BLAKE2s test set " << i << std::endl;
			}

			pass = pass && !fail;
		}
	}

	{
		// One test with salt and personalization for GH #921
		// Test vector generated with modified BLAKE2 ref implementation
		// https://github.com/noloader/cryptopp-test/tree/master/BLAKE2
		const std::string key = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46";
		const std::string salt = "\x41\x42\x43\x44";
		const std::string personalization = "\x41\x42\x43\x44";
		const std::string message = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50";
		const std::string digest = "\x0b\x62\x56\x59\xb0\x0a\xb7\x43\x72\x53\xa2\x6a\x6c\x97\x91\xa4\x83\x74\x95\x27\x55\xc5\xa2\x6d\x89\xcc\x9d\x46\xba\x9a\xff\x57";
		std::string calculated;

		BLAKE2s blake2s(ConstBytePtr(key), BytePtrSize(key), ConstBytePtr(salt), BytePtrSize(salt),
				ConstBytePtr(personalization), BytePtrSize(personalization));
		blake2s.Update(ConstBytePtr(message), BytePtrSize(message));

		calculated.resize(32);
		blake2s.TruncatedFinal(BytePtr(calculated), BytePtrSize(calculated));

		pass = pass && (digest == calculated);
	}

	std::cout << (!pass ? "FAILED   " : "passed   ") << COUNTOF(tests)+1 << " hashes and keyed hashes" << std::endl;

	return pass;
}

bool ValidateBLAKE2b()
{
	std::cout << "\nBLAKE2b validation suite running...\n\n";
	bool fail, pass = true;

	{
		fail = strcmp(BLAKE2b::StaticAlgorithmName(), "BLAKE2b") != 0;
		std::cout << (fail ? "FAILED   " : "passed   ") << "algorithm name\n";
		pass = pass && !fail;
	}

	const BLAKE2_TestTuples tests[] = {
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x12\x71\xCF\x25",
	        0, 0, 4
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\xE4\xA6\xA0\x57\x74\x79\xB2\xB4",
	        0, 0, 8
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\xCA\xE6\x69\x41\xD9\xEF\xBD\x40\x4E\x4D\x88\x75\x8E\xA6\x76\x70",
	        0, 0, 16
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x0E\x57\x51\xC0\x26\xE5\x43\xB2\xE8\xAB\x2E\xB0\x60\x99\xDA\xA1\xD1\xE5\xDF\x47\x77\x8F\x77\x87\xFA\xAB\x45\xCD\xF1\x2F\xE3\xA8",
	        0, 0, 32
	    },
	    {
	        NULLPTR,
	        NULLPTR,
	        "\x78\x6A\x02\xF7\x42\x01\x59\x03\xC6\xC6\xFD\x85\x25\x52\xD2\x72\x91\x2F\x47\x40\xE1\x58\x47\x61\x8A\x86\xE2\x17\xF7\x1F\x54\x19\xD2\x5E\x10\x31\xAF\xEE\x58\x53\x13\x89\x64\x44\x93\x4E\xB0\x4B\x90\x3A\x68\x5B\x14\x48\xB7\x55\xD5\x6F\x70\x1A\xFE\x9B\xE2\xCE",
	        0, 0, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x2A\xF7\xA1\x34\x71\x1C\x5A\x03\xCE\xC8\xFC\xA9\x88\xD9\x9C\x8B\x99\x9A\x95\x33\x0D\xC9\x37\xBE\xE3\x3B\xB3\x0B\xAD\x1B\xE3\x7E\x4F\x66\x81\xF1\xE8\x0E\x64\xA1\x9D\xFC\x86\x83\xF1\xFE\x32\x5D\xAA\xDD\xB8\x1B\xA7\xA3\x88\x3F\x71\x1F\x04\x14\x08\x91\x16\x39",
	        0, 31, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x49\x9A\x63\x97\x86\x14\xB9\x50\xCC\x1D\xA0\xAB\x63\xAF\x3B\xC3\xFF\xBC\x63\xA2\x91\xE5\x2A\xD7\xA8\x11\xD6\xD4\x23\x32\x52\xCF\xA9\xD6\x5A\x19\x51\xBA\x20\xF1\x74\xEF\x7D\x82\x38\xFB\x85\x20\x82\x16\x0B\xC7\x3C\xD0\xD2\x72\x45\x75\x38\x5C\xE4\x17\xB1\xAA",
	        0, 32, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA5\x5B\x85\xDD\x70\x10\xE5\x04\xD3\xB5\x10\xEF\x08\xE1\x95\x40\x19\x69\x82\x87\x44\xFD\xBF\x5B\xE8\xE2\xBB\xE3\x57\x8F\x24\x0B\xFB\x92\xD1\x50\x98\xAC\x06\xED\xC2\xBB\x93\x04\x54\x84\x35\x23\x83\xA1\xB0\x47\x91\x99\x0C\x4C\xA6\xFD\x73\x8D\xE5\x78\xA5\x5E",
	        0, 33, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xB8\xBC\xDA\xB9\x66\xE2\x5A\x76\x72\x38\x55\xD9\x5A\x4E\x8C\x4F\xA9\xEC\x8C\xFF\x0B\x18\x38\x98\x5C\x8C\x90\xBC\x46\x56\x24\xD7\x96\xAB\x26\x2B\x49\x14\xD0\xEE\x91\x69\x9A\x0C\xC3\xE6\xCA\x14\x55\x37\xDA\xF6\x59\x4A\x31\x78\x67\x49\x89\x0E\x84\xDC\xE7\x5D",
	        0, 63, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA1\xD7\x6B\x3B\xB7\xCE\x56\x22\xD1\x13\x94\xDF\xF4\xA2\x04\xEF\x75\x85\xAF\x93\x63\x55\xBF\xCE\xAF\x01\x25\xCA\x17\x65\xC3\xD2\x6E\x67\x71\x95\x33\x18\xE7\xE4\xC1\xFA\xE0\xE6\x24\x8A\xE9\x56\xB7\x63\xE2\xBF\x8F\xB3\xA7\xD4\xD7\xFD\x1A\xC1\xAB\x1F\x17\x77",
	        0, 64, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF3\x26\x82\x25\x97\xE1\x91\x53\xF8\x57\xC6\xD9\x57\x46\x09\xDF\x1E\x05\x81\xF6\x23\xEE\x8B\xBC\xFA\xA1\x9F\x21\xB6\xF3\x1D\xAD\x9F\x4E\x47\x0B\xE6\x3C\x5E\x28\xE9\x11\x1D\xAA\x52\xF2\x6B\x1A\x61\xCF\x61\x1C\xB0\x7D\xE5\x79\x14\x79\x79\xA6\x08\xDF\x76\x4B",
	        0, 65, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x6A\x3F\x90\x50\x84\x5D\x84\xB7\xA2\x43\xF3\xEE\x2C\x7A\x10\x50\xC4\x4C\x5E\x39\xF4\xB8\xCC\x1D\xB3\xF1\x39\x82\x77\x22\x10\x92\x36\x21\xA0\xBA\x13\xCC\x4F\xA3\x1C\x4F\xEC\x1A\x15\x29\x20\x20\x3E\x1A\x06\xEA\xF4\xFF\xCB\x44\x72\x52\x3B\xE5\xE0\x08\x79\x92",
	        0, 127, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xC2\xB8\x8C\x5F\xBD\x61\x0F\xAB\x04\xD3\x40\xAD\x88\x74\x02\x6B\x27\x33\x5C\x6F\x8C\xE5\x93\xC3\x2F\x1A\xE5\xE8\x42\xA6\x07\xCB\xB7\x73\x88\xF3\xF5\xFF\xDC\xBF\xCC\x87\x8F\x56\x1F\xF2\x30\x37\x02\xBE\xC3\x1D\xA7\x8F\x12\x56\x35\x03\x50\xC6\x1E\xD8\xBD\x84",
	        0, 128, 64
	    },
	    {
	        NULLPTR,
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xAD\xE2\x77\xD8\x19\xA7\xBE\xF1\x4E\x47\x92\xDF\x4B\xFD\x1E\x7B\xDE\xC8\x41\x54\x31\xF6\x18\x79\x8B\x7F\x9A\x23\x3C\x6F\xA0\x56\xE6\xB3\x85\xBE\x76\x78\x88\x58\x86\x47\xEB\x48\xC5\x20\x62\xF3\x40\xA5\xB2\xB3\x3F\x33\x18\x3A\x12\xA8\xE9\x9A\x74\x9B\xE8\x8F",
	        0, 129, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x55\xD9\xFB\xF8\x8E\x42\x80\xBF\xE2\x75\xB8\xA7\xA1\xFA\xAD\x7D\xEA\x4B\x65\xB3\xDF\xA2\x92\xE1\xB0\x43\xB6\x36\x74\xB4\xC7\x87\x5D\x68\x02\x21\x39\x49\x0B\x69\x70\xC8\x80\x14\x82\x26\x77\x3D\x2D\x97\xAD\x01\x67\x55\x7D\x54\x62\xA0\x88\x0C\xB3\xFA\x69\x85",
	        31, 0, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xBA\xD4\xD2\x86\x9D\x23\x5A\xBD\x76\x77\x0A\xD4\x28\xFD\x31\x8B\x34\xD6\xAA\x7A\x22\xB7\x2E\x8E\x09\x55\x79\xF9\xE9\xB4\x0D\xB7\xA8\x05\x0E\xAB\x17\xD9\xFC\x97\x97\xA0\x61\x40\xC6\x35\x61\xC1\x9A\x91\xF5\x69\x41\xA1\x3D\x3F\xFE\x8B\xEA\xC8\xC4\xE4\xDD\xD7",
	        31, 31, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x24\x4C\x4F\xD1\x8D\x4B\xEC\xE4\x7E\x45\x25\x33\x75\xBE\x95\xCB\x5D\x20\xA0\xE7\x62\xB4\x81\x62\x74\x12\xFD\x86\x09\x4A\xBB\x35\x6B\x26\xF8\xE4\x5A\x8F\x38\xD2\xA1\x10\x89\xC1\x93\xDB\xB0\xB2\xA7\xD8\xE0\x83\x3D\xE6\x76\x18\xF6\xFE\x1A\x14\xBC\x9E\x63\xEF",
	        31, 32, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x91\x58\xD9\x2B\xF2\x81\x65\xA2\xDE\x73\x9E\x9D\x15\x04\xFB\x9C\x47\x76\x04\xA3\x51\xE6\x84\xEF\x1C\xF0\xF5\xF1\x1B\x5F\xE5\x78\x39\x3D\x23\xCA\x3C\x95\xAB\xB1\xD7\xC1\xE9\x10\x4A\x6C\x51\x46\x6C\x19\x02\x48\x75\xD5\x23\x76\xCF\xCC\x64\x02\x15\xC2\xCF\xD6",
	        31, 33, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xEA\xFA\xD7\x50\xFD\x93\x65\xB6\xA7\x29\x75\x07\x17\x80\xF7\xE2\xE2\xF9\x60\xF3\x9C\x9F\x06\xFC\x13\x16\x79\x66\x7A\x3A\x92\xE2\x75\x79\x71\x89\x34\x5C\x6F\x85\x76\x31\xCF\x7A\x76\xB4\x52\xF5\xDC\xC7\x39\x2A\x39\x1A\x26\xD6\x74\xEA\xF4\xC7\x44\x53\xF6\x43",
	        31, 63, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x5C\x55\x87\x5A\xCA\xF3\x78\x11\x33\x91\x5C\x40\x3C\xE8\xDB\x74\xEA\x68\x4D\x76\x44\x91\x6A\x03\x72\xF7\xAA\x0B\x09\x0A\xAD\xC1\x14\xDF\xC0\x52\x83\x0C\x5A\x75\x2B\x25\x0D\x6F\x7F\x94\xBE\x48\x93\xA2\x19\xED\x2E\x4C\x4C\x47\xA3\xF4\xD0\xBD\x9D\x51\x4A\xDA",
	        31, 64, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA2\x3C\xB9\x96\xBC\x40\x61\x12\xF7\x5A\xE7\xBE\x2F\x04\xBB\xCF\x4F\x6D\x65\x65\xF8\x65\xA6\xF6\x88\x5D\x56\x57\x79\xA3\x11\x33\x37\xD1\x72\x84\xEE\x75\x56\x4E\x00\x52\xF1\x88\x07\xC6\xD6\x4D\xFB\x55\xF0\x25\x39\x70\x51\x35\x1A\x73\x85\x6D\x6B\x26\x7A\x79",
	        31, 65, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x22\xEA\xC1\x75\x7B\xBF\x13\xA1\x91\x8B\x46\x89\x2A\xEC\xEB\x07\x6F\x3F\xF4\x70\x68\x8F\xD3\x6D\xE5\x5B\xB9\x03\x69\x38\xF3\x11\x2E\x1E\x6E\x24\xD9\x60\xB7\x4E\xB1\xD4\x67\x38\xBD\x1B\x45\x7C\xF9\x29\xFC\xBB\x4C\x23\x78\xE3\xE5\xFE\x4A\x2D\xED\xDA\x29\x05",
	        31, 127, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x9C\xAE\xD2\x2D\x53\x1B\x52\x07\x39\x4F\xE4\x9F\xE4\x8D\x55\x2C\xC6\x00\x6D\x61\xA5\x83\xA5\xE7\x10\x3B\x34\xFD\x24\xBD\x4E\xE1\xD0\xC2\x02\x8A\xE2\x86\x57\xF3\xAC\x31\xBD\x51\xDE\xEB\x54\xFD\xEB\x84\x80\x2C\x79\x16\x28\x98\x1E\x3C\x83\x87\xDE\x14\x83\x34",
	        31, 128, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF3\x73\x96\x41\x7B\xEF\x67\xF3\x97\xF5\xCD\x8D\xFD\x79\xAA\xBC\xC7\x95\x70\x48\xC8\xC3\x89\xFE\xEC\x7B\xDB\x23\x43\x1E\xFA\x85\x51\x75\x4E\x04\xB3\xF3\xCB\xA6\x46\x58\x2A\x3E\x22\xBE\xFF\x85\x12\xC9\x2B\xE7\xA7\x93\x78\x47\xF5\xFD\xB8\x43\xAF\xBD\x11\x9A",
	        31, 129, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x0C\xAB\xE4\x02\x57\xEB\xAC\x85\xBC\xD6\x13\xBD\x40\x56\x58\xEC\x0B\x7F\x32\xB4\xDB\xBE\x6A\x31\x57\x60\x25\xC4\xFA\xBB\x3E\xDB\x55\x63\xE8\xD1\x27\x19\xB9\xEE\x9C\x7B\xE0\x0D\x8F\x09\xA4\x66\x5C\x32\x34\x34\xC8\x7F\x66\x00\xB7\x0B\x7B\x9C\x32\x74\xFC\x40",
	        32, 0, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA8\x09\x82\xFC\x9A\x5B\xC7\xC5\xF0\x37\x26\x7B\x86\x5D\x35\xA2\x2E\x4D\x79\xCE\xBE\x99\x56\xD6\x56\xBB\xCA\x48\x4C\xFB\x47\xD9\xF4\xBE\xA2\x7A\x3A\xA3\xA7\x91\x34\x8B\x23\xB4\x84\xD1\x66\x8A\xBC\x0F\x4E\xE4\xF1\x70\x8E\xFB\x1A\x95\x12\x2B\x2F\xFF\x49\x87",
	        32, 31, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE0\xD6\xF6\x98\xC1\x50\xBB\xBF\xC1\x65\x47\x20\xC3\x2A\xD6\xE4\x1E\x3B\x31\xC0\xBA\xCF\x7C\xF8\xF8\xA5\xDB\x17\xCF\x4B\x84\x98\x02\x2D\x23\xF6\x18\x78\x8E\x10\xE2\xD3\x53\x5D\x43\x37\x8E\x3F\x9D\x68\xD2\x99\xBB\xC8\x04\xA7\xF4\xCA\xD2\x5C\x0C\x99\xA8\xF4",
	        32, 32, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x43\x62\x70\x1E\xFE\x4C\x12\x39\x03\x01\x04\xA8\x5E\xB5\x55\xE6\xE9\xE5\x55\x6A\xCE\x80\x18\x1D\x81\xA6\xBA\x87\x92\xAB\xFC\x0C\x54\x83\x09\xD2\x45\xFD\xA6\xBC\x1A\x7E\x79\x45\x74\x06\xCC\x77\x3D\x18\x77\x8C\x0D\x38\x03\xC2\x76\x2B\x91\x6F\xF7\xE8\xCA\x61",
	        32, 33, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x08\x1C\xBA\x80\x31\x39\xDF\x39\x37\xBE\x58\xB7\x22\xB3\x3E\x17\x9D\xBF\xE3\xCC\x02\x3C\x60\x2B\x1A\xB8\xEF\x77\x40\x32\x5A\x23\x8F\x48\x3F\x48\x64\x5E\x35\xA6\xBE\xB5\xBE\x1E\x3C\x35\x19\x15\xDE\x87\x41\xFF\xBB\xC4\x65\xB0\xDD\x4A\x5A\x88\x96\x47\xF5\x48",
	        32, 63, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA5\x35\x83\xFB\x6B\x15\x35\x70\x70\x23\x1A\x21\xC3\xBC\x97\x6C\x9C\x59\xDA\x51\xE4\xC4\x11\xDE\x3F\x04\x4E\x0F\x11\x8B\x9F\x1D\xA5\x26\x12\xBC\x2C\x54\x03\x67\x03\x0D\xD5\xB3\xFB\x34\x67\xE7\x02\xC6\x6F\xD9\x31\x1E\xA6\x5C\xBC\xA3\xFE\x86\x2D\x12\x45\xD7",
	        32, 64, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xD9\x1C\xA9\xC0\xE9\x06\xEF\x1E\xDE\xD4\x84\x42\x89\xCD\x7A\xFF\x96\x92\x3E\x43\xAE\xAC\xC6\xDA\xD5\x2E\x55\x3E\x9A\xAA\x10\x86\x2E\xE9\xE4\xEF\x56\xDF\x9D\xD2\x70\x84\x5A\xF7\xD7\xD6\x58\x99\xE9\x01\xCC\x70\xBE\x98\xE0\x20\x3E\xCB\xCB\xCD\x4A\xD0\xA7\x81",
	        32, 65, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xC5\x0E\x8C\x76\x05\x2D\xA7\x43\x90\x73\x8D\x38\xB0\x6C\x9D\x83\x2C\x14\xB1\x2C\x61\x42\x19\xC9\x82\xC5\x90\xB6\xB6\xCE\x78\xFD\x73\x9A\x2A\x79\x27\xA6\xBA\xAF\xEF\xCE\x68\x1D\x00\x53\x49\x2E\x89\x1E\x4C\x13\x12\x77\x9A\x78\xA5\x0F\x2A\xE7\x73\x78\xE2\x0A",
	        32, 127, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x17\xB1\x1E\x2B\xB1\xDF\x49\xFA\x9A\xD0\xD1\x6E\x79\x33\x2A\x62\xA2\x11\x3B\x5E\xE0\xEF\xA2\x49\x44\x6C\x70\xD2\x69\x69\x7F\x69\xC3\xB4\x0B\x21\x1E\x76\x43\x58\x81\x8E\xA1\x2F\x73\x75\xDB\xC3\x22\xF3\x9C\xB7\x03\x56\x49\x8C\xDE\x60\x5A\xB7\x52\x7A\xA1\x53",
	        32, 128, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE4\xF6\xE4\x01\x8A\xA6\xD0\x8D\xCF\x81\x1D\x38\x60\x5C\xB6\xF5\x83\xAA\xB2\x1F\xC0\xC8\x77\xA5\xA4\x77\xE0\x65\x55\xB7\x34\xFC\x7C\x40\x53\x6A\xEC\x32\x7D\x2A\xA3\xE8\xD0\x31\x91\xA8\x15\x11\x58\xE8\x51\xF7\xA0\xDB\xCA\x8A\x71\x6D\x5B\x19\x7B\x78\xDA\xF7",
	        32, 129, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x0D\x19\x8F\xB3\x01\xE3\x83\x7D\xF1\xB9\x98\xEE\x48\x47\xF5\x1D\x91\x01\xEB\x91\x4A\x85\xFA\x6A\x7E\xBA\x7C\xDB\x12\x69\x45\xD7\x15\x6F\xF2\xF5\x05\x81\x27\xA0\x4A\xE4\xE8\xCF\x43\xD8\x76\x8A\x64\xFE\x9D\x97\x61\xE1\x0B\xC1\xBE\x45\xF9\xFA\x1C\xEB\x4B\xB6",
	        33, 0, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x0E\xC6\xDC\x77\xF3\x78\x55\xDE\xF9\x10\x48\x37\x28\xC6\xC1\x93\x0D\x65\x6B\x51\x20\x78\x48\x90\x10\x01\x1B\x9D\xFC\xDB\xB2\x6E\x6D\xD9\xAC\xF5\x1A\xBE\xEF\xBF\xAF\x46\x99\x61\x65\x53\x50\xA6\x08\x09\x90\x8E\x77\x36\x33\x80\xC1\xD7\x7E\xD2\x59\x8A\xA9\x51",
	        33, 31, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x44\x66\x17\xF1\x0A\xDD\x2A\xCC\x5C\x23\xAF\x6D\x1B\xF8\xE6\x99\x6B\x69\x41\x82\xFD\x7D\x1D\xBD\x83\x44\xF7\x80\x1D\x96\x8F\xF6\xB5\x4A\xA2\x60\x72\x06\x7D\x06\xA6\x11\x87\x44\x27\xAF\x2D\x04\xA7\x8E\xF0\x90\x72\x7F\xED\x05\x90\x36\x27\xD9\x37\xBF\xDF\x9B",
	        33, 32, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xA8\xAE\x4B\x1B\x9C\x20\x5F\xF3\xE8\xBC\xA5\xD0\x8B\xB0\x10\x1F\xB9\xFB\x10\xB5\x29\xB2\xA0\x72\x43\xD8\x75\x08\xF5\x65\x3C\xA8\xB2\x93\x92\x2F\x85\xB2\xE6\xC2\xAF\x72\x30\xDF\x50\x5F\x1F\x60\xFD\x4A\xC5\x02\x4D\xDF\x01\xBD\x83\x4F\xC7\x9A\x9E\x15\xAA\x8B",
	        33, 33, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x88\x18\xC9\xDB\x3A\xD3\x29\x7F\xC3\xC0\x6A\x27\x62\x50\x06\x72\x74\x7D\x60\xAF\x53\xA8\xB0\x4D\xF2\xE2\x9E\x50\xF8\xE8\xFD\x93\x21\x11\x4D\x69\x42\xA0\xD8\x60\xFA\xDD\xEE\x95\x59\xED\x51\x5B\x29\xA9\x19\x4B\xE5\xE5\x5B\x88\x63\x06\x05\xBF\x6E\x57\x3E\xE2",
	        33, 63, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x35\xEC\xD6\x75\x45\x34\xAD\x71\x93\x99\xE8\xC0\xB0\x2F\x0D\xE2\x79\xB1\x7A\x5E\xA3\x54\x59\x3F\x1B\x73\x92\xC4\xAD\x18\xEE\x56\xE1\xE6\x76\x6D\x7B\xCC\x62\xE8\x9C\x38\x56\x7B\xC4\x0A\xE4\x89\x7C\x66\x84\x8C\xB3\x99\xDE\x2E\x60\xDD\x48\xA0\x08\x0A\xDE\xA0",
	        33, 64, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xBA\x5D\xDD\x7B\xE8\x47\xB7\x2D\x90\x17\x52\x66\xDD\x17\x54\xFC\x69\x59\x9D\x43\x1B\x3C\x6D\xE8\x08\x3B\xB2\xEA\xA5\x8C\xDE\xE9\x71\x69\xF5\x62\x22\x14\x67\xC9\xAC\xC2\xB7\xEA\xEA\xAF\x10\x17\xDA\xD8\x52\xFA\x45\x65\x9F\x5E\xAE\x38\xB7\xCF\x01\xD2\x66\x53",
	        33, 65, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x9B\x61\x94\x75\x04\x23\x28\xED\xAF\x0C\x9B\x50\x58\xEB\x5F\xD0\x8F\x78\x16\xA7\x81\xA6\x29\xA1\xEC\x50\xA7\xE6\x41\x53\xE2\x3B\x38\x84\x28\x4C\xE7\x33\x25\xA5\xF2\xB4\xEB\x0C\x7A\x40\xEA\xA0\x39\x54\x76\x7D\x94\xDA\xE7\x2B\x67\x68\x60\xF1\xD2\x8A\x05\xA5",
	        33, 127, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x9C\x18\x11\x0D\x2C\x8D\xE4\x07\x0D\x7F\x99\xB5\x0F\x88\x55\x7C\xBB\xB8\x4C\x8D\xE3\x42\x04\x32\x2C\xF0\x77\x79\xBE\x35\xE2\xEA\x0B\x4B\xA1\x44\x69\xDA\xA6\xFB\xBD\x40\xD6\x66\x5A\x99\x4E\x9E\x7B\x32\x20\xB8\xC7\x34\x3F\xCA\x66\x5C\x86\x2A\x60\x1A\x69\x74",
	        33, 128, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xCB\xEC\x77\x51\x9F\xD7\xAC\x67\xEE\xB7\x8D\xAC\xB8\x1E\xE2\x8D\x3E\x17\x61\x29\xC0\x39\xF5\xDD\xB4\x5A\xC6\x8A\xBB\x40\x55\x81\x03\x7E\x58\x43\x9E\xDD\x36\x08\x04\x96\xCD\xC1\x95\xCF\xF1\x71\x20\x81\x66\x10\x89\xE3\x88\x22\xB8\x5E\x65\xA4\xC8\x8E\xAA\x2A",
	        33, 129, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\x31\xD7\x85\x5E\xBC\xAA\x40\xE2\xEF\xA6\xD4\x35\xC7\x9E\x37\x1E\x80\xBD\x1E\x37\x72\xE6\xEF\xD6\xB1\x41\x1A\xE5\xF8\xB2\x92\x1A\xE0\xAD\x11\xBF\xF0\x57\xD5\x9A\xF8\xC4\x4C\x11\x88\x64\xDA\x88\x45\x3C\xCC\xF7\xCB\x44\x9E\x34\x23\xA3\x9D\x6D\x11\x98\x0B\xAC",
	        63, 0, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x3E\x7E\xA0\x5E\x1B\x64\x0D\x9F\x5B\xDA\xF9\xB8\x56\x4E\x2D\xEC\x99\x5E\xDC\xF3\xAF\x26\xE1\x19\x4E\x1B\xC2\xA6\xDA\x2D\x41\x8A\xDD\xC2\x12\xA6\x54\x6C\x90\x98\x74\x27\x29\xF6\x2D\x94\x55\xA6\x92\x95\x4C\x8E\xD3\x23\x72\x06\xEF\x92\x38\x99\xA6\x9E\xE2\x14",
	        63, 31, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x79\xA5\x33\xEA\x9A\xBC\xBF\xB9\x48\x23\xDF\x8F\x27\x7E\x96\x4A\xB9\x2D\xA7\x3D\xEE\x9E\xBE\x97\x5E\x1B\xC1\x4A\xD0\x19\xF8\xF8\xF4\x6D\x0C\x59\x94\xB3\x6C\x2E\xCA\x18\xD7\xEF\x20\x98\x21\x77\x7E\x07\xEB\x4F\x51\x0C\x82\xCE\xD3\x3F\x48\x82\xBC\x98\x3C\xBA",
	        63, 32, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xF8\x34\x86\xBD\x50\xEC\xB7\x32\x3A\xCC\x9A\x93\x6B\xA6\x45\x3D\xD5\x77\x42\xC7\x88\xC1\x34\xEB\x17\xE4\x0C\x41\xB0\xDD\x4F\xC9\x83\x29\x38\x26\x64\x1C\x21\xC9\xD1\x8A\xA5\xFC\x9F\x64\x5E\xE8\x11\x17\x41\x0C\xE6\xEB\x8C\x73\x93\xF6\xB2\xEB\xEF\xC7\xB8\xBE",
	        63, 33, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x9B\xDF\x77\xB9\xC0\x1F\xC9\xC5\xAA\x6B\x52\x8B\x30\x77\xE5\x1C\xD0\x09\x79\x44\x45\x6D\xB6\x1A\xFF\x1B\xEE\x54\xD1\xE9\x8D\x84\xB9\x53\x5F\x50\x50\x75\x58\x69\x7C\x5C\xEE\x86\xCC\x19\x4D\x3D\x8A\x4F\xCD\x93\x48\xEF\xAE\xBF\x95\x12\x72\x88\x45\xCB\x00\xD3",
	        63, 63, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x79\x8A\xB1\xD6\x8A\x88\x62\x00\xF4\x20\xA6\xC6\x5D\x63\x7D\x2D\xEB\x91\xB9\xDA\x63\xA9\xFF\xC4\x6A\x49\x19\x30\x73\xE2\xDE\x95\x7B\x9A\xEE\x23\xAE\x58\xD9\x58\x91\xFE\x43\x9D\x82\x0B\x95\x50\xE1\x58\x1D\xA6\x93\x70\x84\x4A\x70\xE5\xC2\xED\x28\x39\x5C\x29",
	        63, 64, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xD2\x0E\x26\xF0\xDE\xB8\x75\xEF\xD0\xB9\xD3\x29\x2D\x1F\x94\x46\x62\xB5\x9A\x55\xFB\xAB\x4C\x13\xFF\xB9\x62\x82\x90\x93\x04\xE6\x8B\xA5\x32\x9A\x50\xB9\x2D\xAE\x79\x6B\xC3\xE1\x3E\x58\xE1\x5F\xAB\x9B\xA7\x07\x95\x52\x8B\x60\x5C\x64\x0C\xEB\x15\x93\x16\x2A",
	        63, 65, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x60\x41\x21\xAA\x32\x6A\x49\x68\xDF\xBA\xAE\x5A\xF2\x43\xE6\xA6\x7B\xB7\x4A\x4C\x0D\xD6\xE7\x32\x71\x1E\x24\xCC\x14\xD0\x5F\x5A\x94\x0A\x21\x4F\xBB\x68\xA1\x43\x78\xC8\x71\x8C\x5C\x4E\xB8\x19\x91\xA6\x5B\x1E\x59\x87\x86\xB7\x6F\x5D\xB8\xCB\xF2\xEC\x7C\x50",
	        63, 127, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x5A\xC4\xD5\xD9\xA5\x67\x38\x66\x0B\x18\x67\xF7\xD8\xD3\x4E\x82\x6C\xFA\xC1\x91\x40\x73\x60\xE7\xCA\x0E\x71\x7D\x30\xC8\x55\x88\x25\x83\xCF\xB2\x55\xCA\x9B\xE9\x61\x53\x73\xCF\xB1\xB8\x40\x3F\xC1\x37\xB2\x20\xEB\x4F\x03\xC5\x15\x48\x94\xE6\xAE\xDB\xA4\x60",
	        63, 128, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x0A\x3E\x43\x52\x9D\x71\xDA\x38\x49\xBC\x64\x93\xA9\x43\x78\x1E\xB2\x5B\x79\xE9\xF5\x3F\x1A\xFE\xEB\x41\xBE\x41\x33\xDA\x6B\x31\x2E\xC5\xBD\xD6\xC2\x96\xE2\x4C\xA1\x2C\x05\xA8\x52\x86\x4C\x8F\xEE\x73\x6F\x71\x71\x6D\x5B\x60\xE1\x1C\xAC\x7D\x2F\xC6\x23\x55",
	        63, 129, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        NULLPTR,
	        "\xD9\x38\xD6\xD9\x8F\x0B\xD9\x87\x39\xA6\x59\x19\xD2\xB3\xC9\x14\x9A\x4F\xCE\x6C\x98\xB0\x6A\xF4\xF9\x58\x58\x31\x35\x0B\x57\x47\xC2\xF6\xA7\x82\xA3\x39\x61\xA8\x1B\x62\x59\x7A\x2E\xB1\xE9\xC0\xA5\x80\x3D\xA7\xC5\xD3\x93\x4B\xB2\x0A\x6E\x88\xBA\xA4\xAE\x02",
	        64, 0, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xE9\x47\xAF\x37\x5E\x3D\xBF\x30\x27\x8E\x29\xE6\x39\x0A\x48\x77\x3F\xB0\x0E\x80\x86\xDF\x3B\x98\x8A\x11\x97\xA7\x3C\xBE\x9C\x4A\x23\xAC\x25\x28\xF5\xD0\x9F\xBA\xFC\xDE\xCD\x88\x85\x30\x00\x00\xA3\xC2\x51\xCF\x9A\x41\x88\x00\x02\xA6\xB5\x46\xD2\x58\xB1\xB6",
	        64, 31, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x64\x24\x6B\xA8\x6C\x93\x07\xE2\x62\xC2\x35\xD6\xD9\xA7\xD1\xCD\xFA\xCE\x0A\x12\xB0\x5E\x57\x1C\xBC\x61\xDF\xFB\x59\x6C\x95\xAD\x04\xEF\x02\xCD\x89\xDD\x39\x80\x7D\x78\x3E\x55\x32\x3C\x53\x32\xF3\x91\xFE\x16\x0C\xF9\xF4\x41\xBB\x9E\xF7\xBA\xE6\x0A\xB7\x6F",
	        64, 32, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xB0\x09\xE7\x5A\xBA\x9F\xED\xBE\x3C\xA4\x6A\x93\xF8\x9A\x79\x3A\x01\x8F\x06\xC6\x4A\xA6\xED\xC5\xDD\x21\xDF\x3C\x87\xD4\xBD\xC1\x0E\x29\x3E\x3F\x3B\x6A\x16\x7B\x41\xB8\xB7\x79\xC9\xB2\x16\xD0\xC2\xC2\xF8\xA7\x68\x9B\xB2\x93\x2B\x0A\x43\x58\xC0\x76\xE0\x40",
	        64, 33, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x62\x47\x33\xE4\x70\xCC\xBE\x7A\x64\xE1\xBC\xF4\x37\x0E\x61\x92\xCC\x78\xA0\x1B\x26\x11\x39\x82\x36\x29\x76\xFA\x0A\x2A\x99\x52\xE5\xDC\x08\xB5\xFF\xBC\xEA\x5F\xE7\xDD\x48\xF7\x77\x36\x49\x58\x46\xA3\x53\x38\xCB\xFD\x96\x39\x2C\xDB\x01\x94\x4E\x8D\xCC\xD9",
	        64, 63, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x76\x31\x38\x1F\x2B\x49\xCF\x26\xCA\x9B\xD9\x8F\x48\x09\x67\x50\x6F\x0E\xC3\x26\xC3\x44\x05\xC1\xE5\x8F\x58\x20\x80\xE0\x2F\x47\xAE\xC9\xF4\x5C\x8C\x48\x41\xA5\xF8\xBA\xD3\x24\x60\x64\xBE\x6C\x23\x15\xC8\x36\xC1\x91\xE4\x4A\x76\x8F\x2A\x8D\xBC\x22\x42\x14",
	        64, 64, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x97\x13\x7E\x8C\x18\x22\x5B\x6B\xBC\x61\xF3\x9A\xB4\x10\x77\x91\x43\x80\x05\x9D\x13\x1D\xDC\xA7\x95\x1B\x41\x95\x4D\x49\x6A\xFF\x51\xE1\x03\x87\xCF\x61\x86\x21\x64\x7F\xD6\x4D\x4C\x5A\x49\xC5\xC7\x47\x18\x6F\xDB\x87\xBA\x22\xD3\x4C\xB3\x85\x76\x01\x64\x9D",
	        64, 65, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\xB9\x5F\x66\xD3\x80\xDC\x88\xBF\x0F\x75\xB8\xA7\x0F\x93\xAB\xBB\x46\x34\x8C\x38\xD0\x71\x1F\x83\xAC\x80\x4A\x2C\x68\xFD\xCD\x3C\x82\x31\x83\x3B\x25\xE0\xC4\x5C\xCF\xD7\x4A\x33\x9D\x27\x2E\xC0\x2F\x44\x39\x7C\x9F\xBA\x54\x07\x0B\xA3\x5C\x71\x39\xA0\x9A\x11",
	        64, 127, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x59\xB3\xCE\x2E\x95\xDB\x70\x0A\xA7\x34\xC1\x50\x70\xCA\x57\xDE\x3C\x37\x6C\xB7\x22\xF8\x99\x60\x6E\xE4\x0E\x67\xBF\x7C\x10\xC6\x7C\x16\xDE\x7A\xEF\x06\x02\x13\x3E\x57\x75\xE3\x9A\x4D\x88\xAE\x1C\x32\x07\xEC\x57\x77\x11\x53\x47\x07\x79\x9C\xA8\x60\x30\x96",
	        64, 128, 64
	    },
	    {
	        "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61",
	        "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A",
	        "\x43\x06\xF9\x3E\x7C\xFB\xDE\x72\x5F\x83\x3E\x39\xCD\x07\x57\x89\x9B\xCD\x81\x0F\x83\x51\x56\x18\x19\xB4\x6F\xFD\xA4\x61\x86\x2E\x68\x9C\x55\x5A\xF4\xBC\x88\x46\x04\x5C\xDD\x27\xC6\xE0\x0C\x81\x07\x7C\xC5\x90\x0B\x25\x2D\xF1\xD1\x40\x01\xD8\x39\x69\x3C\x2E",
	        64, 129, 64
	    }
	};

	{
		byte digest[BLAKE2b::DIGESTSIZE];
		for (size_t i=0; i<COUNTOF(tests); ++i)
		{
			// the condition is written in a way which for non-default digest sizes
			// tests the BLAKE2_Base(bool treeMode, unsigned int digestSize) constructor.
			// See https://github.com/weidai11/cryptopp/issues/415
			if (tests[i].dlen < BLAKE2b::DIGESTSIZE && tests[i].key == NULLPTR)
			{
				BLAKE2b blake2b(false, (unsigned int)tests[i].dlen);
				blake2b.Update((const byte*)tests[i].message, tests[i].mlen);
				blake2b.Final(digest);
			}
			else
			{
				BLAKE2b blake2b((const byte*)tests[i].key, tests[i].klen, NULLPTR, 0, NULLPTR, 0, false, (unsigned int)tests[i].dlen);
				blake2b.Update((const byte*)tests[i].message, tests[i].mlen);
				blake2b.Final(digest);
			}

			fail = std::memcmp(digest, tests[i].digest, tests[i].dlen) != 0;
			if (fail)
			{
				std::cout << "FAILED   " << "BLAKE2b test set " << i << std::endl;
			}

			pass = pass && !fail;
		}
	}

	{
		// One test with salt and personalization for GH #921
		// Test vector generated with modified BLAKE2 ref implementation
		// https://github.com/noloader/cryptopp-test/tree/master/BLAKE2
		const std::string key = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c";
		const std::string salt = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c";
		const std::string personalization = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c";
		const std::string message = "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42";
		const std::string digest = "\x0c\xab\x0f\x22\x5d\xbe\xce\x14\xab\xcb\x70\xc9\x90\x69\xc3\xdf\xf5\x08\x18\x51\x90\xa3\x5d\x14\x41\xf2\xac\xb9\x2d\xf0\x5b\x9e\x7c\x2c\x18\x08\xe8\x01\x06\xcf\xb2\x8f\xf3\xe5\x38\xff\xd0\x72\xd8\xa6\xd3\x70\x24\x5b\x86\x61\x7d\x86\xaa\x8d\x64\xb6\xcc\xc6";
		std::string calculated;

		BLAKE2b blake2b(ConstBytePtr(key), BytePtrSize(key), ConstBytePtr(salt), BytePtrSize(salt),
				ConstBytePtr(personalization), BytePtrSize(personalization));
		blake2b.Update(ConstBytePtr(message), BytePtrSize(message));

		calculated.resize(64);
		blake2b.TruncatedFinal(BytePtr(calculated), BytePtrSize(calculated));

		pass = pass && (digest == calculated);
	}

	std::cout << (!pass ? "FAILED   " : "passed   ") << COUNTOF(tests)+1 << " hashes and keyed hashes" << std::endl;

	return pass;
}

bool ValidateSM3()
{
	return RunTestDataFile("TestVectors/sm3.txt");
}

NAMESPACE_END  // Test
NAMESPACE_END  // CryptoPP
